Java的集合类主要由两个接口派生而成:Collection和Map
Collection接口是List、Set和Queue接口的父接口
两种遍历集合元素的方法
- 使用Iterator接口遍历集合元素
- 使用foreach循环遍历集合元素
把一个对象丢进集合中,集合会忘记对象的类型,把集合元素当作Object类型的实例进行处理,JDK1.5之后,可以使用泛型来限制集合里的元素。
使用Iterator接口遍历集合元素
Iterator仅用于遍历集合,依附于Collection对象。
Iterator接口提供三个方法:
- boolean hasNext():如果还有没有被遍历的元素,返回true
- Object next():返回集合中下一元素
- void remove():删除集合里上一次next方法返回的元素
Collection集合中的元素不能被改变,只有remove()方法可以,否则引发异常
使用Iterator对集合进行迭代时,Iterator并没有把集合元素本身传给迭代变量,二是把集合元素的值传给迭代变量,修改迭代变量的值对集合元素没有影响。
Iterator迭代器采用快速失败机制,一旦迭代过程中检测到该集合已经被修改,程序立即引发异常,而不是显示修改过的结果。
使用foreach循环遍历集合元素
过程与使用Iterator接口迭代访问集合元素类似,集合元素同样不能被改变。
Set集合
Set实际上就是Collection,只是行为不同--不允许包含重复元素,没有提供任何额外方法。
判断两个对象相同使用equals方法,比较返回true,Set不会接受这两对象;返回false,会接受。
HashSet类
按哈希算法存储集合元素,存储和查找性能好。特点如下:
- 不能保证元素的排列顺序,排列顺序可能发生变化
- 不同步,若多个线程同时访问一个HashSet,必须通过代码保证同步
- 集合元素可以为null
判断两个元素相等的标准:两个对象通过equals()方法比较相等,并且两个对象的hashCode()方法返回值也相等。
注意:当把一个对象放入HashSet中时,如果需要重写该对象对应类的equals()方法,也应该重写其hashCode()方法。
其规则是:如果两个对象通过equals()方法比较相等返回true,则两个对象的hashCode()值也应该相同。
hashCode()重写规则记住判断两个元素相等的标准
向其中添加可变对象时,小心修改其中的对象,可能导致该对象与集合中其他对象相等,无法准确访问对象
LinkedHashSet类
是HashSet类的子类,根据元素的hashCode值来决定元素的存储位置,但它同时使用链表维护元素的次序,使得元素看起来是以插入的顺序保存的。
遍历元素时,将按添加元素的顺序访问集合中的元素。
由于需要维护插入顺序,性能略低于HashSet的性能。
依然是HashSet,不允许集合元素重复。
TreeSet类
是SortedSet接口的实现类,可以确保集合元素处于排序状态。根据元素值的大小进行排序。采用红黑树存储集合元素。
支持两种排序:自然排序和定制排序。默认情况下,采用自然排序。
自然排序
调用集合元素的compareTo(Object obj)方法比较元素之间的大小关系,然后将集合元素按升序排列
向其中添加元素时,第一个元素无需实现Comparable接口,后面添加的元素必须实现。
大部分类在实现compareTo(Object obj)方法时,需要将被比较对象obj强制类型转换成相同类型。只有两个相同类型的实例才会比较大小
判断两个对象是否相等的唯一标准是:两个对象通过compareTo(Object obj)方法比较是否返回0。
当把一个对象放入TreeSet中,重写该对象对应类的equals()方法时,应保证该方法与compareTo(Object obj)方法有一致的结果
定制排序
想以降序排列,通过Comparator接口的帮助。
List集合
代表了一组有序、可重复的集合,每个集合元素有对应的顺序索引(这样就可以使用for循环遍历元素了)
List接口
与Set相比,增加了根据索引来插入、替换和删除集合元素的方法
判断两个对象相等的标准:通过equals()方法比较返回true
还提供了一个listIterator()方法,返回一个ListIterator对象
ListIterator接口
继承了Iterator接口,增加了如下方法:
- boolean hasPrevious():返回该迭代器关联的集合是否还有上一个元素
- Object previous():返回该迭代器的上一个元素
- void add():在指定位置插入一个元素
增加了向前迭代的功能,还可以通过add方法向List集合中添加元素(Iterator只能删除元素)
ArrayList和Vector
基于数组实现的List类,封装了一个动态的、允许再分配的Object[]数组,两者功能相似,但Vector比较古老,有很多缺点,一般常用ArrayList。
ArrayList是线程不安全的,多个线程修改一个ArrayList集合时,必须手动保持同步。Vector线程安全,性能比ArrayList低。
Vector还有一个子类Stack,使用栈的时候少用,尽量用LinkedList。
Arrays.ArrayList
固定长度的List集合,只能遍历该集合里的元素。不是ArrayList的实现类的实例,也不是Vector实现类的实例。
Queue集合
模拟队列的数据结构
一个PriorityQueue实现类和一个Deque接口
PriorityQueue实现类
比较标准的队列实现类,PriorityQueue保存队列元素的顺序并不是按照加入队列的顺序,而是按照队列的大小重新排序。
先弹出的数据是最小的元素,违反了先进先出的规则。不允许插入null元素,有两种排序方式:自然排序、定制排序
定制排序时不要求元素实现Comparator接口
Deque接口
Queue的子接口,代表一个双端队列,允许从两端操作队列元素,可以当作双端队列也可以当作栈来使用。
Deque的一个实现类:ArrayDeque,基于数组的实现,创建时指定一个numElements参数,用于指定Object[]数组的长度;不指定默认底层数组长度为16。使用栈的数据结构推荐使用ArrayDeque或LinkedList。
LinkedList实现类
List接口的实现类,可以根据索引访问数据,还实现了Deque接口,也可以当作双端队列来使用。
内部以链表的形式保存数据,因此随机访问集合元素时性能较差,但在插入、删除元素时性能非常出色。
ArrayList、ArrayDeque内部以数组的形式来保存集合中的元素,因此随机访问集合元素是性能较好。
Vector也是以数组的形式存储数据的,但因它实现了线程同步功能,性能有所下降。
需要遍历List集合元素,ArrayList、Vector随机访问方法方法好;LinkedList集合,采用迭代器比较好。
经常执行插入、删除操作,采用LinkedList,ArrayList、Vector需要经常重新分配内部数组大小,时间开销大。
多个线程同时访问List集合元素,可考虑使用Collections将集合包装成线程安全的集合。
Map
又称为字典、关联数组
保存具有映射关系的数据,所有的Key放在一起就像一个Set集合,所有的value放在一起又类似于一个List,知识索引不再使用整数,二是另一个对象-key。
Map提供了一个Entry内部类来封装key-value对,而计算Entry存储时只考虑Entry封装的key。Entry包含如下三个方法:
Object getKey():返回该Entry里包含的key值
Object getValue():返回该Entry里包含的value值
Object setValue(V value):设置该Entry里包含的value值,并返回新设置的value值
Hashtable和HashMap实现类
Hashtable,线程安全,HashMap,线程不安全,性能后者大于前者。多个线程访问同一Map对象时,hashtable实现类会更好。
hashtable不允许使用null作为key和value,如果试图把null值放进hashtable中,将会引发NullPointerException异常;但hashMap可以使用null作为key或value。所以hashMap里最多只有一个key-value对的key为null,但可以有无数多个key-value对的value为null。
Hashtable,HashMap判断两个key相等的标准是:两个key通过equals()方法比较返回true,两个key的hashCode值也相等。
判断两个value相等的标准是:通过equals()方法比较返回true。
尽量不要使用可变对象作为Hashtable,HashMap的key。
LinkedHashMap实现类
HashMap的子类,使用双向链表维护key-value对的次序,迭代顺序与key-value对的插入顺序保持一致,使用==判断元素相等。
Collections--操作集合的工具类
查找、替换操作
同步控制
提供了多个synchronizedXxx()方法,该方法可以将指定集合包装成线程同步的集合,解决线程安全问题。
Collection c=Collections.synchronizedCollection(new ArrayList());
List list=Collections.synchronizedList(new ArrayList());
设置不可变集合