集合类型 描述
ArrayList 一种可以动态增长和缩减的索引序列
LinkedList 一种可以在任何位置进行高效地插入和删除操作的有序序列
ArrayDeque 一种在循环数组实现的双端队列
HashSet 一种没有重复元素的无序集合
TreeSet 一种有序集
EnumSet 一种包含枚举类型值的集
LinkedHashSet 一种可以记住元素插入次序的集
PriorityQueue 一种允许高效删除最小元素的集合
HashMap 一种存储键/值关联的数据结构
TreeMap 一种键值有序排序的映射表
EnumMap 一种键值属于枚举类型的映射表
LinkedHashMap 一种可以记住键/值项添加次序的映射表
WeakHashMap 一种其值无用武之地后可以被垃圾回收器回收的映射表
IdentityHashMap 一种用==而不是用equals比较键值的映射表
1.链表:
在Java程序设计语言中,所有链表实际上都是双向链接的
链表在添加元素和删除元素等操作上的速度比数组快很多,但是链表是一个有序集合,每个对象的位置十分重要。链表自身的add方法只能添加在链表尾部,这个时候只有通过迭代器中的add方法才能够添加。尽管Iterator没有add方法,但是子接口ListIterator中有add方法可以解决这个问题。
其中ListIterator还有两个方法可以用来反向遍历链表:
E previous()
boolean hasPrevious()
和Iterator一样,在使用方法之前必须先得到迭代器:
ListIterator<String> iter = staff.listIterator();
值得注意的是,remove方法与add方法不太一样,remove方法依赖于迭代器的状态,add方法只依赖迭代器的位置
链表不支持快速的随机访问,每一次访问都需要从头开始,虽然LinkedList类还提供了get方法来访问特定的元素:
LinkedList<String> list = ...; String obj = list.get(n);
get方法做了微小的优化;如果索引大于size()/2就从尾部开始搜索元素
迭代器还有一个自动检测的功能,也就是,当使用两个或者多个迭代器同时对链表进行操作时就会报
ConcurrentModificationException异常
2.java.util.List<E> 1.2:
ListIterator<E> listIterator()
返回一个列表迭代器,以便用来访问列表中的元素
ListIterator<E> listIterator(int index)
返回一个列表迭代器,以便用来访问列表中的元素,这个元素是第一次调用next返回的给定索引的元素
void add(int i , E element)
在指定位置添加一个元素
void addAll(int i , Collection<? extends E> elements)
将某个集合中的所有元素添加到给定位置
E remove(int i)
删除给定位置的元素并返回这个元素
E get(int i)
获得给定位置的元素
E set(int i,E element)
用新元素替换给定位置的元素,并返回原来那个元素
int indexOf(Object element)
返回与指定元素相等的元素在列表中第一次出现的位置,如果没有这样的元素将返回-1
int lastIndexOf(Object element)
返回与指定元素相等的元素在列表中最后一次出现的位置,如果没有这样的元素将返回-1
3.java.util.ListIterator<E> 1.2:
void add(E newElement)
在当前位置添加一个元素
void set(E newElement)
用新元素取代next或previous上次访问的元素。如果在next或previous上次调用之后列表结构被修改了,将抛出IllegalStateException异常
boolean hasPrevious()
当反向迭代列表时,还有可供访问的元素,返回true
E previous()
返回前一个对象。如果已将到达列表的头部,就会抛出一个NoSuchElementException异常
int nextIndex()
返回下一次调用next方法时将返回的元素索引
int previousIndex()
返回下一次调用previous方法时将返回的元素索引
4.java.util.LinkedList<E> 1.2:
LinkedList()
构造一个空链表
LinkedList(Collection<? extends E> elements)
构造一个链表,并将集合中所有的元素添加到这个链表中
void addFirst(E element)
void addLast(E element)
将某个元素添加到列表的头部或尾部
E getFirst()
E getLast()
返回列表头部或尾部的元素
E removeFirst()
E removeLast()
删除并返回列表头部或尾部的元素
5.数组列表:
ArrayList封装了一个动态再分配的对象数组
对于经验丰富的程序员,可能会选择使用Vector类。因为Vector类的所有方法都是同步的,可以有两个线程安全的访问一个Vector对象。但是,如果一个线程访问Vector,代码要在同步操作上耗费大量的时间
6.散列表:
之前谈到的链表和数组都是有序的排列的,也就是说需要知道他们的位置才能够得到相应的数据。如果在不知道位置的情况下想要得到相应的数据,这个时候就可以使用散列表。
散列表为每个对象计算一个整数,也称为散列码,可以联系之前的hashCode方法,这就是产生散列码的途径
在Java中,散列码用链表数组实现。每个列表称为桶。要想查找表中对象的位置,就要先计算它的散列码,然后与桶的总数取余,得到的结果就是保存这个元素的桶的索引。在遇到桶被占满的情况(散列冲突),就会比较元素是否重复
在Java SE 8中,桶满时会从链表变为平衡二叉树。如果需要再散列,就需要创建一个桶数更多的表,并将所有元素插入到这个新表中。这里还涉及一个装填因子,也就是在散列表占用百分之几时再散列
Set就很好的利用了散列表的特性,因为set是一个没有重复元素的元素集合,可以在add和contain时根据散列值快速定位到相应的桶,从而查看是否重复和存在。Java集合类库提供了一个HashSet类,实现了基于散列表的集
散列集迭代器依次访问所有的桶,但是散列将元分散在表的各个位置,所以访问它们的顺序几乎是随机的
7.java.util.HashSet<E> 1.2:
HashSet()
构造一个空散列表
HashSet(Collection<? extends E> elements)
构造一个散列表,并将集合中的所有元素添加到这个散列集中
HashSet(int initialCapacity)
构造一个空的具有指定容量的散列集
HashSet(int initialCapacity , float loadFactory)
构造一个具有指定容量和装填因子的空散列集
8.java.lang.Object 1.0:
int hashCode()
返回这个对象的散列码。散列码可以是任何整数,包括正数或负数
9.树集:
TreeSet类与散列集十分类似,但是比散列集有所改进
树集是一个有序集合,可以以任意顺序将元素插入到集合中,但是在对集合进行遍历时,每个值将自动按照排序后的顺序呈现,当前实现使用的是红黑树
所以将一个元素添加到树中要比添加到散列表中的慢,但是,与检查数组或链表中的重复元素相比还是快很多
查找新元素的正确位置平均需要log2n次比较
所以要使用数集,必须能够比较元素。这些元素必须实现Comparable接口,或者构造集时必须提供一个Comparator
Java SE 6起,TreeSet类实现了NavigableSet接口,这个接口增加了几个便于定位元素以及反向遍历的方法
10.java.util.TreeSet<E> 1.2:
TreeSet()
TreeSet(Comparator<? super E> comparator)
构造一个空树集
TreeSet(Collection<? extends E> elements)
TreeSet(SortedSet<E> s)
构造一个树集,并增加一个集合或有序集中的所有元素
11.java.util.SortedSet<E> 1.2:
Comparator<? super E> comparator()
返回用于对元素进行排序的比较器
E first()
E last()
返回有序集中的最小元素或最大元素
12.java.util.NavigableSet<E> 6:
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<E> descendingIterator()
返回一个按照递减顺序遍历集中元素的迭代器
13.队列与双端队列:
Java SE 6中引入了Deque接口,并由ArrayDeque和LinkedList类实现,这两个类都是双端队列,在必要时也可以增加长度
14.java.util.Queue<E> 5.0:
boolean add(E element)
boolean offer(E element)
如果队列没有满,将元素添加到尾部会返回true,但是如果满了,第一个方法会抛出IllegalStateException异常,第二个方法会返回false
E remove()
E poll()
假设队列不变,删除并返回这个队列头部的元素。如果队列是空的,第一个方法抛出NoSuchElementException,而第二个方法返回null
E element()
E peek()
如果队列不空,返回这个队列头部的元素,但不删除。如果为空,第一个方法抛出NoSuchElementException,而第二个方法返回null
15.java.util.Deque<E> 6:
void addFirst(E element)
void addLast(E element)
boolean offerFirst(E element)
boolean offerLast(E element)
将给定的对象添加到双端队列的头部或尾部。如果满了,前面两个方法将抛出IllegalStateException,后面两个方法返回false
E removeFirst()
E removeLast()
E pollFirst()
E pollLast()
这是删除头部元素的方法,为空的情况下前两个抛出NoSuchElementException异常,后者返回null
E getFirst()
E getLast()
E peekFirst()
E peekLast()
如果队列非空,返回队列头部信息,但不删除。如果队列空,前面两个方法将抛出一个NoSuchElementException
16.java.util.ArrayDeque<E> 6:
ArrayDeque()
ArrayDeque(int initialCapcity)
用初始容量16或给定的初始容量构造一个无限双端队列
17.优先级队列:
优先级队列中的元素可以按照任意的顺序插入,却总是按照排序的顺序进行检索,也就是说,无论何时调用remove方法,总会获得当前队列中最小的元素
然而优先级队列并没有对所有的元素进行排序
优先级队列使用的数据结构称为堆,堆是一种可以自我调整的二叉树,对树执行添加和删除操作,可以让最小元素移动到根
优先级队列既可以实现保存实现了Comparable接口的类对象,也可以保存在构造器中提供的Comparator对象
使用优先级队列的经典示例就是任务调度
18.java.util.PriorityQueue 5.0:
PriorityQueue()
PriorityQueue(int initialCapcity)
构造一个用于存放Comparable对象的优先级队列
PriorityQueue(int initialCapacity , Comparator<? super E> c)
构造一个优先级队列,并用指定比较器对元素进行排序