下表列出了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 |
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 |
构造一个容量为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 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不会再添加新元素时调用这个方法。 |
当添加完所有的元素后,可以把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 ListIterator ListIterator |
清空列表; 判断列表是否为空; 返回元素个数; 查询是否包含某个元素; 返回迭代器对象; 返回迭代器对象,从给定的索引位置开始; 返回功能更多的迭代器对象; 。。。 |
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 也要考虑在内。
/** 示例:如果要按字符串长度进行排序,可以定义这样一个类来实现Comparaor接口
* 它的compare方法返回两个字符串长度的差值
*/
class LengthComparator implements Comparator<String> {
public int compare(String first, String second) {
return first.length() - second.length();
}
}
...
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 |
构造一个树集,并添加给定的集合中的所有元素,如果给定的是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 |
返回一个按递减顺序遍历集中元素的迭代器 |
NavigableSet |
返回集的一个反向排列的视图 |
SortedSet NavigableSet |
返回一个子集,所有元素小于toElement; |
返回一个子集,所有元素小于(当inclusive为true时可以等于) toElement
子集是对源集元素的直接引用!
|
| SortedSet
NavigableSet
返回一个子集,所有元素大于(当inclusive为true时可以等于) fromElement
子集是对源集元素的直接引用! |
| SortedSet
NavigableSet
也可以用boolean参数设定包不包含 |