------------android培训、java培训、期待与您交流!------------
1, 面向对象语言对事物的体现都是以对象的形式,所以为了方便对多个对象的操作,就对对象进行存储,集合就是存储对象最常用的一种方式。集合体系 :
数组和集合类同是容器,它们的区别是:
数组虽然也可以存储对象,但 长度是固定的 ;
集合长度是可变的。数组中可以存储基本数据类型, 集合只能存储对象 。
集合类的特点:集合只用于存储对象,集合长度是可变的,集合可以存储不同数据类型的对象。
2, 出现这么多容器,因为每一个容器对数据的存储方式都有不同。这个存储方式我们称之为:数据结构。
集合框架:
5,集合类的比较与总结:
3, Collection定义了集合框架的共性功能, 集合中存储的都是对象的引用(地址) 。
1)添加
add(e); // add方法的参数类型是Object。以便于接收任意类型对象。
addAll(collection);
2)删除
remove(e);
removeAll(collection);
clear();
3)判断。
contains(e);
isEmpty();
4)获取
iterator();
size();
5)获取交集。
retainAll();
6)集合变数组。
toArray();
4, 迭代器 Iterator的原理:
迭代器 其实就是集合的取出元素的方式, 会直接访问集合中的元素, 所以将迭代器通过内部类的形式来进行描述。 通过容器的iterator()方法获取该内部类的对象。
class CollectionDemo{ public static void main(String[] args) { ArrayList al = new ArrayList(); //1,添加元素。 al.add("java01"); //add(Object obj);
/*Iterator it = al.iterator(); //获取迭代器,用于取出集合中的元素。 while(it.hasNext()){ sop(it.next()); }*/
//应用for形式,迭代器用完即释放。更节省内存。 for(Iterator it = al.iterator(); it.hasNext() ; ){ sop(it.next()); } }
}
1)Collection,List,Set,Map都属于集合框架中的接口。
Collection,Map是顶层接口。List,Set继承Collection接口。
2)List:列表,元素是有序的(元素带角标索引),可以 有重复元素 ,可以有null元素。
Set:集合,元素是无序的(因为没有索引),元素 不可以重复 。可以有null元素。
Map:顶层接口,该集合存储的是键值对,而且 键是唯一的 。
3)Map和Set很像,因为 Set集合底层就是使用了Map集合。
Map集合没有迭代器,要取出元素必须先将Map集合转换成Set集合才能遍历元素。
4)实现List接口的常用类:
4. 1),ArrayList(JDK1.2):
底层的数据结构: 数组数据结构。
特点:查询速度快(因为带角标),但是增删速度稍慢,因为当元素多时,增删一个元素则所有元素的角标都得改变, 线程不同步 。默认长度是10,当超过长度时,按50%延长集合长度。
4. 2),LinkedList(JDK1.2):
底层数据结构: 链表数据结构(即后面一个元素记录前一个)。
特点:查询速度慢,因为每个元素只知道前面一个元素,但增删速度快,因为元素再多,增删一个,只要让其前后的 元素重新相连即可, 线程是不同步 的。
4.3),Vector(JDK1.0):
底层数据结构: 数组数据结构。
特点:查询和增删速度都很慢。默认长度是10,当超过长度时,按100%延长集合长度。 线程同步 。
注意: Vector功能跟ArrayList功能一模一样,已被ArrayList替代。
5)实现Set接口的常用类:
5.1),HashSet(JDK1.2):
底层数据结构: 哈希表。
特点: 存取速度快,元素唯一,线程不同步。
保证性元素唯一的原理:
先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true。
注意: 往HashSet里面存的自定义元素要复写hashCode和equals方法,以保证元素的唯一性。
5. 2),TreeSet(JDK1.2):
底层数据结构: 二叉树 。
特点: 可以对Set集合中的元素进行排序。元素有序,线程不同步。
保证元素唯一性的依据:compareTo方法return 0。
TreeSet排序的第一种方式:
让元素自身具备比较性,比如八种基本数据类型或则字符串,实现Compareble接口,覆盖compareTo方法, 此方式是元素的自然顺序。
TreeSet排序的第一种方式:
当元素自身不具备比较性(比如存储学生对象时)或者具备的比较性不是我们所需要的比较性时(比如想字符串的长度排序),此时就需要让集合自身具备自定义的比较性。可在集合初始化时,就让集合具备比较方式。即定义一个类,实现Comparator接口,覆盖compare方法。
6)实现Map接口的常用类:
6. 1),HashTable(JDK1.0):
底层数据结构: 哈希表。
特点:不可以使用null键和null值,线程同步,效率低。
注意:用作键的对象必须实现hashCode和equals方法来保证键的唯一性。
6. 2),HashMap(JDK1.2):
底层数据结构: 哈希表。
特点:允许使用null键和null值,线程不同步,效率高;
保证元素唯一性的原理:先判断元素的hashCode值是否相同,再判断两元素的equals方法是否为true。
6. 3),TreeMap(JDK1.2):
底层数据结构: 二叉树。
特点:允许使用null键和null值,线程不同步,可以给Map集合中的键进行排序。
TreeMap排序的第一种方式:
让元素自身具备比较性,比如八种基本数据类型或则字符串,实现Compareble接口,覆盖compareTo方法, 此方式是元素的自然顺序。
TreeMap排序的第一种方式:
当元素自身不具备比较性(比如存储学生对象时)或者具备的比较性不是我们所需要的比较性时(比如想字符串的长度排序),此时就需要让集合自身具备自定义的比较性。可在集合初始化时, 就让集合具备比较方式。即定义一个类,实现Comparator接口,覆盖compare方法。
6, List: 特有方法,凡是可以操作角标的方法都是该体系特有的方法。
增 add(index,element);
addAll(index,Collection);
删 remove(index);
改 set(index,elenment);
查 get(index);
subList(from,to);
listIterator();
在迭代时,不可以通过集合对象的方法操作集合中的元素, 因为集合和迭代器同时拥有元素对象的引用。此时迭代器去操作集合,有可能发生并发修改异常,即 ConcurrentModificationException异常。
如果想要其他的操作如添加,修改等,就需使用 Iterator的子接口 ListIterator, List集合特有的迭代器。
该接口只能通过List集合的listIterator方法获取。
import java.util.*;
class ListDemo {
public static void main(String[] args) {
ArrayList al=new ArrayList();
//添加元素
al.add("java01");
al.add("java02");
System.out.println ("原集合是:"+al);
for( al.listIterator() ;li.hasNext();) {
System.out.println ("hasPrevious:"+li.hasPrevious());
Object obj=li.next();
if(obj.equals("java02")) {
li.set("java006");
li.add("java009");
}
System.out.println("hasNext():"+li.hasNext());
System.out.println ("hasPrevious:"+li.hasPrevious());
}
}
}
7, 枚举就是Vector特有的取出方式 , 其实枚举和迭代是一样的。 因为枚举的名称以及方法的名称都过长,所以被迭代器取代了。
import java.util.*;
class VectorDemo {
public static void main(String[] args) {
Vector v=new Vector();
v.add("java01");
v.add("java02");
for(Enumeration en=v.elements();en.hasMoreElements();) {
System.out.println(en.nextElement());
}
}
}
8, LinkedList:
特有方法:
addFirst();
addLast();
getFirst();
getLast();获取元素,但不删除元素。如果集合中没有元素,会出现NoSuchElementExceptionremoveFirst();
removeLast();获取元素,但是元素被删除。如果集合中没有元素,会出现NoSuchElementException
在JDK1.6出现了替代方法。
offerFirst();
offerLast();
peekFirst();
peekLast();获取元素,但不删除元素。如果集合中没有元素,会返回null
pollFirst();
pollLast();获取元素,但是元素被删除。如果集合中没有元素,会返回null
使用LinkedList模拟一个堆栈或者队列数据结构。
堆栈:先进后出FILO
队列:先进先出FIFO
import java.util.*;
class Queue{
private LinkedList link;
Queue(){
link=new LinkedList();
}
public void myAdd(Object obj) {
//头插法,保证先进先出。
link.addFirst(obj);
}
public Object myGet() {
return link.removeLast();
}
public boolean isNull(){
return link.isEmpty();
}
}
class LinkedListTest{
public static void main(String[] args) {
Queue d=new Queue();
d.myAdd("java01");
d.myAdd("java02");
while(!d.isNull()){
System.out.println(d.myGet());
}
}
}
9,1)ArrayList保证元素唯一,即去除重复元素。需要定义一个临时容器, 用contains方法判断,同时需要复写equals方法。
public static ArrayList singleElement(ArrayList al){
//定义一个临时容器。
ArrayList newAl=new ArrayList();
for(Iterator it=al.iterator();it.hasNext();){
Object obj=it.next();
if(!newAl.contains(obj))
newAl.add(obj);
}
return newAl;
}
2)HashSet保证元素唯一。 复写hashCode(),equals(Object obj)方法。
public int hashCode() {
return name.hashCode()+age*39; //扩大范围,避免出现重复值
}
public boolean equals(Object obj){ //注意:此处参数必须是Object,才能复写Object类中的equals方法。
if(!(obj instanceof Person))
return false;
Person p=(Person)obj;
return this.name.equals(p.name)&&this.age==p.age;
}
10, 当元素自身不具备比较性,或者具备的比较性不是所需要的。这时需要让容器自身具备比较器。
当两种排序都存在时,以比较器为主。
class TreeSetDemo{
public static void main(String[] args){
//将自定义的 比较器作为参数传递给TreeSet构造函数。
TreeSet<Student> ts=new TreeSet<Student>(new MyCompare());
ts.add(new Student("lisi02",22));
ts.add(new Student("lisi007",20));
ts.add(new Student("lisi09",19));
for(Iterator<Student> it=ts.iterator();it.hasNext();){
Student s=it.next();
System.out.println(s.getName()+'\t'+s.getAge());
}
}
//第二种排序方法,自定义一个比较器,当两种排序同时存在时,此种方法生效。
class MyCompare implements Comparator<Student>{
//复写compare 方法。
public int compare(Student o1,Student o2){
//此处使用泛型,不用强转。
//Student s1=(Student)o1;
//Student s2=(Student)o2;
if(!o1.getName().equals(o2.getName()))
return o1.getName().compareTo(o2.getName());
else
return new Integer(o1.getAge()).compareTo(new Integer(o2.getAge()));
}
}
//第一种排序方法, 强制让学生具备比较性。
class Student implements Comparable<Student>{
private String name;
private int age;
Student(String name ,int age){
this.name=name;
this.age=age;
}
//复写compareTo方法。
public int compareTo(Student obj){
if(!(obj instanceof Student))
throw new RuntimeException("不是学生对象");
Student s=(Student)obj;
System.out.println(this.name+"..compareTo.."+obj.name);
if(this.age!=obj.age)
return this.age-obj.age;//降序为s.age-this.age
else
return this.name.compareTo(obj.name); //降序为s.name.compareTo(this.name);
}
}
11,泛型 :JDK1.5版本以后出现新特性,用于解决安全问题,是一个类型安全机制。
好处:1)将运行时期出现的问题ClassCastException,转移到编译时期。方便于程序员解决问题。让运行时期问题减少。
2)避免了强制转换的麻烦。
泛型格式:通过<>来定义要操作的引用数据类型。
在使用java提供的对象时,泛型,通常在集合框架中很常见。
只要见到<>就要定义泛型,其实<>就是用来接收类型的。
当使用集合时,将集合中要存储的数据类型作为参数传递到<>中即可。
class GenericDemo{
public static void main(String[] args){
ArrayList<String>al=new ArrayList<String>();
al.add("abc01");
//al.add(new Integer(4)); //编译时报错,泛型在编译时期检查类型。
for(Iterator<String> it=al.iterator();it.hasNext();){
String s=it.next();
System.out.println(s+'\t'+":"+s.length());
}
}
}
12,自定义泛型。
1)泛型定义在类上。
当类中要操作的引用数据类型不确定时,早期定义Object来完成扩展,现定义泛型来完成扩展。
class Utils<Q>{
private Q q;
public void setObject(Q q){
this.q=q;
}
public Q getObject(){
return q;
}
}
2)泛型定义在方法上。 方法 声明泛型应紧靠返回值的前面。
泛型类定义的泛型,在整个类中有效,如果被方法使用,那么泛型类的对象明确要操作的具体类型后,所有要操作的类型就已经固定了。为了让不同方法可以操作不同类型,而且类型还不确定,那么可以将泛型定义在方法上。 class Demo<T>{ //泛型类
public void show(T t){
System.out.println("show:"+t);
}
public <Q>void print(Q q){ //泛型方法。
System.out.println("print:"+q);
}
public static <W>void method(W t){ //泛型定义在静态方法上。
System.out.println("method:"+t);
}
}
特殊之处:静态方法不可以访问类上定义的泛型。因为类上的泛型只对该类的对象有效。
如果静态方法操作的引用数据类型不确定,可以将泛型定义在方法上。
3)泛型定义在接口上。
interface Inter<T> {
void show(T t);
}
class InterImpl<T> implements Inter<T> {
public void show(T t) {
System.out.println("show:"+t);
}
}
13, ?通配符,也可以理解为占位符。
泛型的限定:
?extends E:可以接收E类型或者E的子类。上限。
?super E:可以接收E类型或者E的父类型。下限。
public static void printColl(ArrayList<?> al) {
for(Iterator<?> it=al.iterator();it.hasNext();) {
System.out.println(it.next());
//.length()不可以,具体的类型方法。
//.toString()可以,所有对象都具备此方法。
}
}
14 , Map集合:该集合存储键值对。一对一对往里存,而且要保证键的唯一性。
1)添加。
put(K key,V value); //注意此处添加为put。
putAll(Map<? extends K,? extends V> m);
2)删除。
clear();
remove(Object key);
3)判断。
containsKey(Object key);
containsValue(Object value);
isEmpty();
4)获取。
get(Object key);
size();
values();
entrySet();
keySet();
Map集合的取出原理:将map集合转成Set集合,再通过迭代器取出。
Map集合的两种取出方式:
1)Set<K> keySet:
将Map中所有的键存入到Set集合,因为set具备迭代器,所以可以用迭代方式取出所有的键,
再根据get方法,获取每一个键对应的值。
//先获取map集合中的所有键的Set集合,keySet();
Set<String> keySet=map.keySet();
//有了Set集合就可以获取其迭代器。
for(Iterator<String> it=keySet.iterator();it.hasNext();) {
String key=it.next();
//有了键就可以通过Map集合的get方法获取其对应的值。
String value=map.get(key);
System.out.println("key:"+key+"...value:"+value);
}
2)Set<Map.Entry<K,V>> entrySet:将map集合中的映射关系存入到set集合中, 而这个关系的数据类型就是:Map.Entry。
//将Map集合中的映射关系取出,存入到Set集合中。
Set<Map.Entry<String,String>> entrySet=map.entrySet();
for(Iterator<Map.Entry<String,String>> it=entrySet.iterator();it.hasNext();) {
Map.Entry<String,String> me=it.next();
String key=me.getKey();
String value=me.getValue();
System.out.println(key+":::"+value);
}
15,其他API。
1)集合框架的工具类 Collections
二分查找:
binarySearch(List<?
extends Comparable<? super T>> list, T key)
替换列表中的所有元素:
fill
(
List
<? super T> list, T obj)
2)集合变数组:toArray();
目的: 为了限定对元素的操作。不需要进行增删。
String[] s=al.toArray(new String[al.size()]);
// 当指定的数组长度小于了集合的size,那么该方法内部会创建一个新的数组
Arrays.toString(s);
3) 高级for循环,JDK1.5的新特性。
格式: for(数据类型 变量名:被遍历的集合(Collection)或者数组) { }
对集合进行遍历, 只能获取元素,不能对集合进行操作。
迭代器除了遍历,还可以remove集合中元素的动作。 如果使用ListIterator,还可以在遍历过程中进行增删改查的动作。
传统for和高级for的区别: 高级for有一个局限性,必须有被遍历的目标。
建议在遍历数组的时候,还是希望使用传统for,因为传统for可以定义角标。
4) 方法的可变参数, JDK1.5版本的新特性。
在使用是注意:可变参数一定定义在参数列表的最后边。
public static void show(int... arr) {
System.out.println(arr.length);
}
5) StaticImport 静态导入,JDK1.5的新特性。
import java.util.*;
//导入Arrays这个类中的所有静态成员。
import static java.util.Arrays.*;
//导入了System类中所有的静态成员。
import static java.lang.System.*;
class StaticImport{
public static void main(String[] args){
out.println("haha");
int[] arr={3,1,5};
sort(arr);
int index=binarySearch(arr,1);
out.println(Arrays.toString(arr));
out.println("Index:"+index);
}
}
注意: 当类名重名时,需要制定具体的包 名。
当方法重名时,需要指定具体所属的对象或者类。
------------android培训、java培训、期待与您交流!------------
详情请查看:http://edu.csdn.net/heima