下表列出了Java类库中的主要集合类,为了便于区分,这个表里面没有包括线程安全集合。在下表中,以Map结尾的类实现了Map接口,而其它类都实现了Collection接口。

类名 描述
ArrayList 可以动态缩放的一个索引序列
LinkedList 可以在任意位置进行快速插入删除的有序序列
ArrayDeque 用循环数组实现的双端队列
HashSet 没有重复元素的无序集合
TreeSet 有序集合
EnumSet 包含枚举类型的集合
LinkedHashSet 可以记住元素插入顺序的集合
PriorityQueue 可以快速删除最小元素的集合
HashMap 存储键 / 值对的数据结构
TreeMap 键按树形结构实现的Map
EnumMap 键是枚举类型的Map
LinkedHashMap 可以记住键值对添加次序的Map
WeakHashMap 值没有被其它地方引用时,就会被GC回收的Map
IdentityHashMap 用==而不是equals比较键的Map

Java集合类库之Collection - 图1

1 ArrayList

ArrayList 内部是一个对象数组,在添加和删除元素时,ArrayList能够自动调整数组容量,把装满的数组移到新建的更大的数组中。

老版本Java中,Vector类也可以实现动态数组,但是在单线程中使用ArrayList更加高效。只有在多线程中才使用Vector。

ArrayList 的容量(capacity)和大小(size)有重要的区别。大小是 ArrayList 对象实际包含的元素个数,它等价于普通数组的 length。容量是 ArrayList 对象内部数组的长度,这个长度总是大于或等于size,并且可以变化。
ArrayList 是AbstractList的子类,实现了Iterable<E>, Collection<E>, List<E>, RandomAccess, Serializable, Cloneable 接口。Collectionadd, addAll, remove, removeAll, removeIf, contains, size, isEmpty方法,Listget, set, indexOf, lastIndexOf, subList, iterator, listIterator方法都可以直接用。
从Collection继承来的add方法有返回值,因为Colletion要兼顾Set(不允许重复元素),添加操作可能不会改变Set对象,需要区分true或false。而List中add操作一定成功,除非抛异常或内存用尽。

java.util.ArrayList
方法声明 用途
ArrayList() 构造一个空ArrayList
Arrayist(int initialCapacity) 构造一个容量为initialCapacity的空ArrayList
ArrayList(Collection<? extends E> c) 构造一个包含了参数中所有元素的ArrayList,顺序由参数的iterator方法返回的顺序决定。
void add(int index, E obj) 在第index的位置插入一个元素,那个位置上原来的元素以及后面的元素全部向后移动。
boolean add(E e) 在ArrayList尾部添加一个元素
boolean addAll(int index, Collection<? extends E> c) 在ArrayList的index的位置插入给定的集合中的所有元素
boolean addAll(Collection<? extends E> c) 在ArrayList尾部添加给定的集合中的所有元素
boolean remove(Object o)

boolean removeAll(Collection<?> c)

boolean retainAll(Collection<?> c)
遍顺序历列表,给定的元素第一次出现的时候,删除它;
删除包含在给定的集合对象中的元素;

删除给定的集合对象中不存在的元素。
E get(int index)
E set(int index, E element)
E remove(int index)
void removeRange(int fromIndex, int toIndex)

List subList(int fromIndex, int toIndex)



int indexOf(Object o)
int lastIndexOf(Object o)
查找、
替换
或删除给定位置的元素(包含fromIndex,不包含toIndex),操作成功就返回该位置原来的元素。

返回指定范围的一个子列(包含fromIndex,不包含toIndex),
子列直接引用源列表中的元素可以在子列中进行结构性的修改,但是子列之外的结构性修改是没有定义的

返回给定元素第一次出现的索引(找不到返回-1
返回给定元素最后一次出现的索引(找不到返回-1
void ensureCapacity(int minCapacity) 这个方法通常用来手动增加ArrayList容量,这样可以确保ArrayList 对象至少可以存储minCapacity个元素,而不用再重新分配内部数组。
void trimToSize() 将ArrayList 的容量削减到当前的元素的数量。垃圾回收器将回收削掉的空间。这时候添加新元素就会再次移动存储块,所以应该在确认ArrayList不会再添加新元素时调用这个方法。
T[] toArray(T[] a) 当添加完所有的元素后,可以把ArrayList转换为普通数组,方便用下标进行访问。比如有一个确定大小的ArrayList变量 list:T[] a = new T[list.size()]; list.toArray(a);
boolean removeIf(Predicate<? super E> filter) 从集合中删除满足fileter条件的元素,如果这些元素删除成功,返回true
void clear()
boolean isEmpty()
int size()
boolean contains(Object o)
Iterator iterator()
Iterator iterator(int index)
ListIterator listIterator()
ListIterator listIterator(int index)
清空列表;
判断列表是否为空;
返回元素个数;
查询是否包含某个元素;
返回迭代器对象;
返回迭代器对象,从给定的索引位置开始;
返回功能更多的迭代器对象;
。。。

2 LinkedList

与数组的连续存储不同,链表每个元素都是独立的节点,每个节点还存放着下一个节点的引用。Java里的链表都是双向链表——即每个节点还存放着前驱节点的引用。得益于链表的结构,从链表中间增删元素非常快。
LinkedList 是 AbstractSequentialList 的子类,实现了 Collection<E>, List<E>, Iterable<E>, ``Serializable, Cloneable, Deque<E>, Queue<E>接口。可以在LinkedList上进行队列的操作。
虽然LinkedList也可以像ArrayList一样,用整数索引进行添加,删除,查找,替换的操作,但是每次都要从头开始搜索,效率很低,应该尽量避免使用以索引表示链表中位置的方法。
listIterator 方法返回一个实现了 ListIterator 接口的对象,可以用它来遍历链表元素,参看ListIterator
LinkedList 拥有的方法和ArrayList基本一样(只不过没有ensureCapacity, trimToSize),下面是一些不一样的

java.util.LinkedList
方法签名 用途
LinkedList() 构造一个空链表
LinkedList(Collecion<? extends E> elements) 构造一个链表,并将集合中所有元素添加进去
void addFirst(E e)
void addLast(E e)
将某个元素添加到链表头部或尾部
E getFirst()
E getLast()
返回链表头部或尾部的元素
E removeFirst()
E removeLast()
删除并返回链表头部或尾部的元素

3 HashSet

如果想查看指定的元素,却不记得它的位置,就要在集合里一个一个查找,效率很低。当不需要关心元素的顺序时,可以用散列表来组织数据。散列表存储每个元素的散列码,散列码是一个由数据元素的实例字段算出来的整数。可以用hashCode方法得到这个整数。Java用链表数组实现散列表,每个链表称为桶(bucket)。查找一个元素,要先计算它的散列码,然后对桶的总数取余,余数就是这个元素所在的桶的索引。散列码相同的元素被放到一个桶中。每次添加新元素,要将它与桶里所有元素进行比较,查看对象是否已经存在。最好的情况是,散列码均匀地随机分布,桶的数目也很多,一个桶里只装一个元素,所以添加元素只要比较一次。
Java8开始,桶满时(达到8个元素)从链表变成平衡二叉树,来提高查找的性能。而元素减少到6个时变回来。
当一个散列表中,有75%的桶装填了元素,就会自动对所有元素再次散列,创建一个两倍桶数的散列表。0.75叫做装填因子,是一个默认值。散列表总的桶数默认为16个。
HashSet 是 AbstractSet 的子类,实现了 Iterable<E>, Collection<E>, Set<E>, Serializable, Cloneable 接口。

java.util.HashSet
方法签名 用途
HashSet() 构造一个空散列集
HashSet(Collection<? extends E> elements) 构造一个散列集,将集合的所有元素添加进去
HashSet(int initialCapacity) 构造一个散列集,并指定桶数
HashSet(int initialCapacity, float loadFactor) 构造一个散列集,指定桶数和装填因子(0.0~1.0)

最后强调一下,HashSet 中的元素没有顺序。

4 TreeSet

TreeSet是一个有序集合,每次向TreeSet对象添加一个元素时,都会自动将其放在正确的序列位置上。因此迭代器总是以有序的方式访问元素。向树集添加元素比较慢,但是在树集中查询元素比在链表中快很多。正如类名一样,TreeSet的排序是用树状数据结构实现的,当前Java使用的是红黑树。

向树集添加的元素必须能够被比较,这些元素要么实现Comparable接口,要么在构造树集时提供一个Comparator对象。 另外,从原则上来说,Set接口约定使用equals方法来判定两个元素是否相等,而TreeSet实际上采用的是compareTo方法或Comparator来判定。因此,为了保持概念上的一致性,应该尽可能保证compareTo 和equals 有同样的相等性规则。还有 hashCode 也要考虑在内。

  1. /** 示例:如果要按字符串长度进行排序,可以定义这样一个类来实现Comparaor接口
  2. * 它的compare方法返回两个字符串长度的差值
  3. */
  4. class LengthComparator implements Comparator<String> {
  5. public int compare(String first, String second) {
  6. return first.length() - second.length();
  7. }
  8. }
  9. ...
  10. TreeSet<String> ts = new TreeSet<String>(new LengthComparator);

TreeSet 是 AbstractSet 的子类,实现了 Iterable<E>, Collection<E>, Set<E>, SortedSet<E>, NavigableSet<E>, Serializable, Cloneable 接口。NavigableSet 增加了几个查找元素以及反向遍历的方法。

java.util.TreeSet
方法签名 用途
TreeSet()
TreeSet(Comparator<? super E> comparator)
构造一个空树集
TreeSet(Collection<? extends E> elements)
TreeSet(SortedSet s)
构造一个树集,并添加给定的集合中的所有元素,如果给定的是SortedSet,则使用跟它相同的元素顺序。
boolean add(E e)
boolean addAll(Collection<? extends E> c)
添加元素
下面是在 java.util.SortedSet 声明的方法
Comparator<? super E> comparator() 返回元素的比较器,如果没有使用比较器,元素自己实现了Comparable接口,则返回null
E first()
E last()
返回当前集的第一个(最小)元素;
返回当前集的最后一个(最大)元素;
下面是在 java.util.NavigableSet 声明的方法
E higher(E value)
E lower(E value)
返回大于value的最小元素;
返回小于value的最大元素;
如果没有则返回null
E ceiling(E value)
E floor(E value)
返回大于等于value的最小元素;
返回小于等于value的最大元素;
如果没有则返回null
E pollFirst()
E pollLast()
删除并返回这个集中的最大或最小元素,集为空时返回null
Iterator descendingIterator() 返回一个按递减顺序遍历集中元素的迭代器
NavigableSet descendingSet() 返回集的一个反向排列的视图
SortedSet headSet(E toElement)
NavigableSet headSet(E toElement, boolean inclusive)
返回一个子集,所有元素小于toElement;

返回一个子集,所有元素小于(当inclusive为true时可以等于) toElement
子集是对源集元素的直接引用!
| | SortedSet tailSet(E fromElement)
NavigableSet tailSet(E fromElement, boolean inclusive) | 返回一个子集,所有元素大于等于fromElement
返回一个子集,所有元素大于(当inclusive为true时可以等于) fromElement
子集是对源集元素的直接引用! | | SortedSet subSet(E fromElement, E toElement)
NavigableSet subSet(E fromElement, boolean fromInclusive, E toElement, boolean toInclusive) | 返回包含两个值之间的元素的集,默认是包含fromElement,不包含toElement;
也可以用boolean参数设定包不包含 |