TimZhi 2009-09-12
数组:固定长度
集合框架
集合(集合类的对象)是用来管理其他若干对象的。它类似于C++标准模板库中的容器,不过在JAVA的集合类的对象中可以用来存放多种类型的
对象。
接口和类共同构成了一个集合框架,集合的概念,一个对象可以装载多个对象,这个对象就是集合对象。
1,接口
Collection
↑
|ˉˉˉˉˉˉ|
SetListMap
↑↑
||
SortedSetSortedMap
集合中用到的类,接口在java.util包中,在使用时注意将其引入import。
Collection接口:用来管理多个对象,集合中的每个元素都是对象。
1)List接口:一个List的实现类的对象在管理多个对象时会按顺序组织对象(即按照将对象放入的顺序存储)
List实现类的对象是有顺序的,List实现类对象中的内容是可重复的。(注意,顺序和排序的区别)
List接口的特点:有序存放,允许重复,可放不同类型对象
2)Set接口:一个Set的实现类表示一个数学概念上的集合,Set的实现类的对象中的元素是无顺序的,也就是不会按照输入顺序来存
放,
Set的实现类对象中的元素是不重复的。
Set接口的特点:无序存放,不允许重复,也可以存放不同类型对象
3)SortedSet接口:它是Set的子接口,他的实现类会对集合中的元素进行排序。但是要指定排序规则,他会按排序规则进行排序。
Map,Map中没有对象,而是键值对,由Key,value组成的键值对
Key是没有顺序,不可重复的。
value是可以相同的,一个Key和一个value一一对应。
Map接口(以下介绍其子接口)
SortedMap,这个接口的实现类同样可以实现,不过是对键值对中的Key进行排序,这个接口的实现类也是要指定排序规则的
2、List接口的实现类
Collection
↑
|ˉˉˉˉˉˉ|
HashSetLinkedListHashtable
(Set)Vector,ArrayListHashmap
(List)(Map)
↑↑
||
TreeSetTreeMap
(SortedSet)(SortedMap)
Collection接口的方法:
add(Objecto)
addAll(Collectionc)
contains(Objecto)
containsAll(Collectionc)
remove(Objecto)
removeAll(Collectionc)
clear()
equals(Objecto)
isEmpty()
iterator()
size()
toArray()
toArray(Object[]o)
Iteratorit=hs.iterator();
for(Objectobj;it.hasNext();){
obj=it.next();
...
System.out.println(obj);
}
1>ArrayList是接近于功能的集合类,ArryList的实质就是一个会自动增长的数组,ArrayList是用封装的数组来实现的List接口的,
底层用数组实现的。
Collection的实现类对象的遍历方式是用迭代来实现的。
在使用迭代器时先要获得一个迭代器的对象,Iterator(迭代器接口)这是一个接口,迭代器是在集合类中实现的,
也就是说,他是一个内部类(匿名内部类)实现的。
Iterator接口中定义的常用方法方法hasNext(),next()。
hasNext(),这个方法会使用一个游标,并通过判断游标指向的位置是否存放有对象。
next()方法也是Iterator接口中定义好的方法,这个方法会使游标指向下一个元素的位置,游标会跳过第一个元素,并返回
其中的内容。
Collections这是一个工具类,也是java.util包中的,这个类中的sort(list接口的实现类的对象)方法,其参数是一个集合
类的对象,
这个方法使用来对集合类的对象进行排序的。以后,我将以集合这个名字来称呼集合类的对象。对于字符串对象内容的集合
来说会按字典顺序排序(升序),
对于数字内容的集合排序也会按照升序排序。
排序可分为两部分内容,一个是排序的规则,也就是按照什么来进行排序,并且排成什么样的顺序。
第二个就是排序的算法,他决定了排序的效率。
在对自定义的集合内容类型排序时,需要先定义那个类型的排序规则。
Comparable接口,这个接口中只定义了一个compareTo(Objecto),方法的返回至类型是整型,如果当前对象大于参数对象就
返回正数,当前对象等于参数对象是就返回0,当前对象小于参数对象时就返回负值,这样写就是升序排列,反之则是进行降序排列
,在实现这个接口中的方法时,返回值定义方式,只有这两种
根据指定类型的排序规则实现了Comparable接口,那么就可以对存有这个类型的集合进行整体排序。Comparable接口,也叫
做可比较接口。
这个接口在java.lang包下。只要实现了这个接口,就是可排序的。
接下来介绍另外一种对自定义类型对象的集合整体排序的方法,也就是实现比较器接口(Comparator),
这个接口中定义了一个compare(Objecto1,Objecto2)方法来比较两个对象,这个方法的返回值定义和上面介绍的那个方法
是一样。
注意:在API,帮助文档中以上两个方法的参数类型是T,这代表的模板类型,也就是集合中存放的内容的类型,在JDK1.4中
其参数就是Object类型,
模板类型的详细内容会在最后的JDK5.0新特性中讲到。
Comparator接口可以在匿名内部类中实现,Collections中的sort(集合了的对象,比较器)方法,可以对自定义类型内容的
集合进行整体排序。
2>LinkedList,它是List接口的实现类,其底层是用双向循环链表来实现的。
注意:ArrayList的查询效率比较高,增删动作的效率比较差,适用于查询比较频繁,增删动作较少的元素管理的集合。
LinkedList的查询效率低,但是增删效率很高。适用于增删动作的比较频繁,查询次数较少的元素管理集合。
ArrayList,LinkedList都是线程不安全的。
3>Vector:底层用数组实现List接口的另一个类
特点:重量级,占据更多的系统开销线程安全
(与ArrayList相似,区别是Vector是重量级的组件,使用使消耗的资源比较多。)
结论:在考虑并发的情况下用Vector(保证线程的安全)。
在不考虑并发的情况下用ArrayList(不能保证线程的安全)。
java.util.stack(stack即为堆栈)的父类为Vector。可是stack的父类是最不应该为Vector的。因为Vector的底层是数组,
且Vector有get方法(意味着它可能访问到并不属于最后一个位置元素的其他元素,很不安全)。
对于堆栈和队列只能用push类和get类。
Stack类以后不要轻易使用。
实现栈一定要用LinkedList。
实现堆栈1,数组(ArrayList,增删效率比较低,不适合)
2,LinkedList(实现堆栈的好方法)
3,java.util.Stack类,Stack是Vector的子类,Vector类是一个线程安全的(是一个重量级的类),并继承了Vector的方法
,
Verctor类和ArrayList的功能近乎相同。(不推荐使用Stack类来实现堆栈)。
3、Set接口的实现类
3.1HashSet
Set的实现类的集合对象中不能够有重复元素,HashSet也一样他是使用了一种标识来确定元素的不重复,HashSet用一种算法来保证
HashSet中的元素是不重复的,HashSet采用哈希算法,底层用数组存储数据。默认初始化容量16,加载因子0.75
Object类中的hashCode()的方法是所有子类都会继承这个方法,这个方法会用Hash算法算出一个Hash(哈希)码值返回,HashSet会用
Hash码值去和数组长度取模,
模(这个模就是对象要存放在数组中的位置)相同时才会判断数组中的元素和要加入的对象的内容是否相同,如果不同才会添加进去
。
Hash算法是一种散列算法。
Seths=newHashSet();
hs.add(o);
|
o.hashCode();
|
o%当前总容量(0--15)
|
|不发生冲突
是否发生冲突-----------------直接存放
|
|发生冲突
|假(不相等)
o1.equals(o2)-------------------找一个空位添加
|
|是(相等)
不添加
覆盖hashCode()方法的原则:
1、一定要让那些我们认为相同的对象返回相同的hashCode值
2、尽量让那些我们认为不同的对象返回不同的hashCode值
3、尽量的让hashCode值散列开(两值用异或运算可使结果的范围更广)
注意:所以要存入HashSet的集合对象中的自定义类必须覆盖hashCode(),equals()两个方法,才能保证集合中元素不重复。在覆盖
equals()和hashCode()方法时,
要使相同对象的hashCode()方法返回相同值,覆盖equals()方法再判断其内容。为了保证效率,所以在覆盖hashCode()方法时,
也要尽量使不同对象尽量返回不同的Hash码值。
如果数组中的元素和要加入的对象的hashCode()返回了相同的Hash值(相同对象),才会用equals()方法来判断两个对象的内容是否相
同。
3.2SortedSet接口是Set的子接口。TreeSet是SortedSet接口的实现类
TreeSet底层用二叉树实现。它可以对集合中的元素进行排序。
要存放在TreeSet中自定义类的对象,这个类要么是已经实现了Comparable接口,要么是能给出Comparator比较器,
TreeSet可以自动过滤掉重复元素所以不用重载hashCode()方法,TreeSet会根据比较规则判断元素内容是否相同,TreeSet会在元素存
入时就进行了排序。
(在TreeSet给出排序规则时,一定要注意对象内容相等的条件,一定要注意在主观的认为两个对象内容相同时,才可以使用比较少的
条件来进行判断)
在要排序时才使用TreeSet类(存储效率比较低),HashSet的,,存储效率比较高,在需要为HashSet的对象排序时,就可以把HashSet
中的元素放入TreeSet。
Iterator:迭代器java.util
Iterable:可迭代的java.lang
Comparator:比较器java.util
Comparable:可比较的java.lang
Collection使用总结:
如果涉及到堆栈,队列等操作,应该考虑用List。
对于需要快速插入,删除元素,应该使用LinkedList。
如果需要快速随机访问元素,应该使用ArrayList。
如果程序在单线程环境中,或者访问仅仅在一个线程中进行,考虑非同步的类,其效率较高;如果多个线程可能同时操作一
个类,应该使用同步的类。
要特别注意对哈希表的操作,作为key的对象要正确覆盖equals()和hashCode()方法。
尽量返回接口而非实际的类型,如返回List而非ArrayList,这样如果以后需要将ArrayList换成LinkedList时,客户端代码
不用改变。
补充:Collections类提供了很多用于操作集合的静态方法:Collections.sort(List)、Collections同步方法等
Set,List,Map的区别和功能到底是怎样的?其实它是与数组区分开来的。与数学中的集合最接近,两者都不包含重复元素。它的有些实现类能对集合中的键对象进行排序。切记在用到MAP时一定需要传入两个参数