谈到JAVA里的容器,首先应该了解JAVA中的容器相关接口。这些接口规定了不能容器的功能。
最顶层的接口是Collection和Map。Collection是单元素的容器,Map是双元素——即键值对形式。Collection下面又派生出了诸如List、Queue、Set等接口。通常这些接口都有对应的抽象类:比如AbstrctCollection就是实现了Collection接口的抽象类,这些抽象类的作用是提供一些基本实现,减少实现这些接口的工作量。下面介绍各接口的主要特点和区别:

  1. List: 特点是可随机读取,可以在任意位置插入、删除、添加元素。按元素添加顺序排列。常用的有:ArrayList、LinkedList。
  2. Queue:队列,特点是先进先出,且只能。派生出接口Deque,即双端队列。常用的实现类包括:PriorityQueue,即堆;LinkedList。
  3. Map:不包含重复项,无法使用下标,以键值对的形式存在。常用的实现类包括:HashMap: 元素无序,也不知道元素的添加顺序;LinkedHashMap: 可以按元素添加顺序访问;TreeMap: 元素有序。
  4. Set: 也不允许重复。常用的实现类跟Map相对应包括:HashSet;LinkedHashSet;TreeSet。且这些类在实现上也是依赖对应的Map类。

接下来具体介绍各容器类的特点:
5. ArrayList: 用数组实现。访问指定位置的元素很快,时间复杂度为O(1);但是删除和插入效率很低,需要进行元素的移动,在元素数量大于数组长度时需要扩容。
6. LinkedList: 双向链表实现。实现了List、Deque接口,因此同时也是个双端队列。由于使用链表实现,因此访问指定位置的元素较慢,但是删除和插入效率很高。适合在需要频繁删除和插入的情形下使用。
7. ArrayDeque: 双端队列,用数组实现。数组的实现方式是把整个数组看成是首尾相接的(也就是说数组第0个元素的前一个元素是数组的最后一个元素,多以当head == tail时,表示数组空间已经被占满了,需要扩容)。不过,它还支持对队列中间元素的操作。
8. HashMap:用Hash表实现,解决冲突的办法是链地址法。也就是每个元素实际上存放的是一个桶,桶里存放的是单向链表;当链表节点树超过8(源码中的静态常量TREEIFY_THRESHOLD)时,自动转换成红黑树结构。
9. HashSet:内部维护一个HashMap数据,添加数据时,被添加数据作为key存入HashMap中,value值为固定的PRESENT(一个object对象),利用HashMap中的数据唯一性保证自身的数据唯一性。
10. TreeSet: 内部维护一个TreeMap数据(不过转换成了TreeMap所实现的NavigableMap类型)
11. TreeMap:红黑树实现,有序。注意:Key的类型必须实现接口Compareble,否则运行出错;或者在实例化TreeMap时提供比较器。
12. LinkedHashMap: 在HashMap的基础上添加了双向链表以实现按添加顺序遍历的功能,具体做法是在HashMap的节点类Node派生新的类Entry, Entry中添加两个变量Entry<K,V>before,after用来指向上一个和下一个节点。