Java 集合工具包位于 Java.util 包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。
分为如下五个部分:List 列表、Set 集合、Map 映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。
Java 集合类的整体框架如下:
从上图中可以看出,集合类主要分为两大类:Collection 和 Map。
Collection 是 List、Set 等集合高度抽象出来的接口,它包含了这些集合的基本操作,它主要又分为两大部分:List 和 Set。
List 接口通常表示一个列表(数组、队列、链表、栈等),其中的元素可以重复,常用实现类为 ArrayList 和 LinkedList,另外还有不常用的 Vector。另外,LinkedList 还是实现了 Queue 接口,因此也可以作为队列使用。
Set 接口通常表示一个集合,其中的元素不允许重复(通过 hashcode 和 equals 函数保证),常用实现类有 HashSet 和 TreeSet,HashSet 是通过 Map 中的 HashMap 实现的,而 TreeSet 是通过 Map 中的 TreeMap 实现的。另外,TreeSet 还实现了 SortedSet 接口,因此是有序的集合(集合中的元素要实现 Comparable 接口,并覆写 Compartor 函数才行)。 我们看到,抽象类 AbstractCollection、AbstractList 和 AbstractSet 分别实现了 Collection、List 和 Set 接口,这就是在 Java 集合框架中用的很多的适配器设计模式,用这些抽象类去实现接口,在抽象类中实现接口中的若干或全部方法,这样下面的一些类只需直接继承该抽象类,并实现自己需要的方法即可,而不用实现接口中的全部抽象方法。
Map 是一个映射接口,其中的每个元素都是一个 key-value 键值对,同样抽象类 AbstractMap 通过适配器模式实现了 Map 接口中的大部分函数,TreeMap、HashMap、WeakHashMap 等实现类都通过继承 AbstractMap 来实现,另外,不常用的 HashTable 直接实现了 Map 接口,它和 Vector 都是 JDK1.0 就引入的集合类。
Iterator 是遍历集合的迭代器(不能遍历 Map,只用来遍历 Collection),Collection 的实现类都实现了 iterator() 函数,它返回一个 Iterator 对象,用来遍历集合,ListIterator 则专门用来遍历 List。而 Enumeration 则是 JDK1.0 时引入的,作用与 Iterator 相同,但它的功能比 Iterator 要少,它只能再 Hashtable、Vector 和 Stack 中使用。
Arrays 和 Collections 是用来操作数组、集合的两个工具类,例如在 ArrayList 和 Vector 中大量调用了 Arrays.Copyof() 方法,而 Collections 中有很多静态方法可以返回各集合类的 synchronized 版本,即线程安全的版本,当然了,如果要用线程安全的结合类,首选 Concurrent 并发包下的对应的集合类。
ArrayList 简介
ArrayList 是基于数组实现的,是一个动态数组,其容量能自动增长,类似于 C 语言中的动态申请内存,动态增长内存。
ArrayList 不是线程安全的,只能在单线程环境下,多线程环境下可以考虑用 collections.synchronizedList(List l) 函数返回一个线程安全的 ArrayList 类,也可以使用 concurrent 并发包下的 CopyOnWriteArrayList 类。
ArrayList 实现了 Serializable 接口,因此它支持序列化,能够通过序列化传输,实现了 RandomAccess 接口,支持快速随机访问,实际上就是通过下标序号进行快速访问,实现了 Cloneable 接口,能被克隆。
LinkedList 简介
LinkedList 是基于双向循环链表(从源码中可以很容易看出)实现的,除了可以当作链表来操作外,它还可以当作栈,队列和双端队列来使用。
LinkedList 同样是非线程安全的,只在单线程下适合使用。
LinkedList 实现了 Serializable 接口,因此它支持序列化,能够通过序列化传输,实现了 Cloneable 接口,能被克隆。
Vector 简介
Vector 也是基于数组实现的,是一个动态数组,其容量能自动增长。
Vector 是 JDK1.0 引入了,它的很多实现方法都加入了同步语句,因此是线程安全的(其实也只是相对安全,有些时候还是要加入同步语句来保证线程的安全),可以用于多线程环境。
Vector 没有实现 Serializable 接口,因此它不支持序列化,实现了 Cloneable 接口,能被克隆,实现了 RandomAccess 接口,支持快速随机访问。
HashMap 简介
HashMap 是基于哈希表实现的,每一个元素都是一个 key-value 对,其内部通过单链表解决冲突问题,容量不足(超过了阈值)时,同样会自动增长。
HashMap 是非线程安全的,只是用于单线程环境下,多线程环境下可以采用 concurrent 并发包下的 concurrentHashMap。
HashMap 实现了 Serializable 接口,因此它支持序列化,实现了 Cloneable 接口,能被克隆。
Hashtable 简介
HashTable 同样是基于哈希表实现的,同样每个元素都是 key-value 对,其内部也是通过单链表解决冲突问题,容量不足(超过了阈值)时,同样会自动增长。
Hashtable 也是 JDK1.0 引入的类,是线程安全的,能用于多线程环境中。
Hashtable 同样实现了 Serializable 接口,它支持序列化,实现了 Cloneable 接口,能被克隆。
LinkedHashMap 简介
LinkedHashMap 是 HashMap 的子类,与 HashMap 有着同样的存储结构,但它加入了一个双向链表的头结点,将所有 put 到 LinkedHashmap 的节点一一串成了一个双向循环链表,因此它保留了节点插入的顺序,可以使节点的输出顺序与输入顺序相同。
LinkedHashMap 可以用来实现 LRU 算法(这会在下面的源码中进行分析)。
LinkedHashMap 同样是非线程安全的,只在单线程环境下使用。