---
url: https://chenlj.top/md/java-base/base/Collection.md
---
# java 集合总结

Java 集合工具包位于 Java.util 包下，包含了很多常用的数据结构，如数组、链表、栈、队列、集合、哈希表等。学习 Java 集合框架下大致可以分为如下五个部分：**List**列表、**Set**集合、**Map**映射、迭代器（**Iterator**、**Enumeration**）、工具类（**Arrays**、**Collections**）。

## java 集合接口继承体系图

Java 集合类的整体框架如下：

![接口](http://qiniu.chenlj.top/20200412/159b15c282834b60b6c812ccfae8c893.jpg)

从上图中可以看出，集合类主要分为两大类：**Collection**和**Map**。

**Collection**是**List**、**Set**等集合高度抽象出来的接口，它包含了这些集合的基本操作，它主要又分为两大部分：**List**和**Set**。

## Collection 接口常用方法

| 返回值类型    | 方法                              | 解释                                                               |
| ------------- | --------------------------------- | ------------------------------------------------------------------ |
| boolean       | add(E e)                          | 向列表的尾部添加指定的元素（可选操作）                             |
| boolean       | addAll(Collection\<? extends E> c) | 将指定 collection 中的所有元素都添加到此 collection 中（可选操作） |
| void          | clear()                           | 移除此 collection 中的所有元素（可选操作）                         |
| boolean       | contains(Object o)                | 判断集合是否包含此元素，包含返回 true                              |
| boolean       | equals(Object o)                  | 比较此 collection 与指定对象是否相等                               |
| int           | hashCode()                        | 返回此 collection 的哈希码值                                       |
| boolean       | isEmpty()                         | 如果此 collection 不包含元素，则返回 true                          |
| Iterator< E > | iterator()                        | 返回在此 collection 的元素上进行迭代的迭代器                       |
| boolean       | remove(Object o)                  | 删除第一次出现在集合的指定元素，返回值为被删除的元素（如果存在）   |
| int           | size()                            | 返回列表中的元素数                                                 |
| Object\[]      | toArray()                         | 返回按适当顺序包含列表中的所有元素的数组（不常用）                 |

## 一、List 集合

> List 接口通常表示一个列表（数组、队列、链表、栈等），其中的元素可以重复，常用实现类为 ArrayList 和 LinkedList，另外还有不常用的 Vector。另外，LinkedList 还是实现了 Queue 接口，因此也可以作为队列使用。
>
> List 接口子实现类的特点
>
> * ArrayList：底层结构是数组，增删慢，查询快（线程不安全，效率高）
> * Vector：底层结构是数组，增删，查询都很慢（线程安全，因此查询效率比 ArrayList 要低）
> * LinkedList：内部是链表数据结构，，增删元素的速度很快（线程不安全）

List 集合特有的常用方法
| 返回值类型 | 方法 | 解释 |
| ---------- | ---- | ---- |
|boolean| addAll(Collection\<? extends E> c) |按照迭代器返回的元素顺序，将指定集合插入到指定集合中|
|boolean |addAll(int index, Collection\<? extends E> c)| 从指定的位置开始，将指定 collection 中的所有元素插入到此列表中|
|E| get(int index) |返回列表中指定位置的元素|
|int| indexOf(Object o) |返回该元素第一次出现在集合中的索引值；若不包含该元素，则返回 -1|
|int| lastIndexOf(Object o)| 返回该元素最后一次出现在集合中的索引值；若不包含该元素，则返回 -1|
|ListIterator< E >| listIterator()| 返回此列表元素的列表迭代器（按适当顺序）|
|E| remove(int index)| 根据索引删除元素，返回值为被删除的元素|
|E| set(int index, E element) |根据索引，修改集合中的元素，返回值为替换前的元素|

### 1.1、ArrayList 集合特点及方法

> ArrayList 是基于数组实现的，是一个动态数组，其容量能自动增长。
>
> ArrayList 不是线程安全的，只能用在单线程环境下，多线程环境下可以考虑用 Collections.synchronizedList(List l)函数返回一个线程安全的 ArrayList 类，也可以使用 concurrent 并发包下的 CopyOnWriteArrayList 类。
>
> ArrayList 实现了 Serializable 接口，因此它支持序列化，能够通过序列化传输，实现了 RandomAccess 接口，支持快速随机访问，实际上就是通过下标序号进行快速访问，实现了 Cloneable 接口，能被克隆。
>
> 特点：数据存储的结构是数组结构。元素增删慢，查找快，由于日常开发中使用最多的功能为查询数据、遍历数据，所以 ArrayList 是最常用的集合。

常用方法：全部继承自 List 接口

### 1.2、LinkedList 集合的特点及方法

> LinkedList 是基于双向循环链表（从源码中可以很容易看出）实现的，除了可以当做链表来操作外，它还可以当做栈、队列和双端队列来使用。
>
> LinkedList 同样是非线程安全的，只在单线程下适合使用。
>
> LinkedList 实现了 Serializable 接口，因此它支持序列化，能够通过序列化传输，实现了 Cloneable 接口，能被克隆。
>
> 特点：数据存储的结构是链表结构。元素增删快，查找慢。实际开发中对一个集合元素的添加与删除经常涉及到首尾操作，而 LinkedList 提供了大量首尾操作的方法

常用方法：

| 返回值类型 | 方法          | 解释                                                            |
| ---------- | ------------- | --------------------------------------------------------------- |
| void       | addFirst(E e) | 将指定元素插入此列表的开头                                      |
| void       | addLast(E e)  | 将指定元素添加到此列表的结尾                                    |
| E          | getFirst()    | 返回此列表的第一个元素（链表为空，抛出 NoSuchElementException） |
| E          | getLast()     | 返回此列表的最后一个元素                                        |
| E          | removeFirst() | 移除并返回此列表的第一个元素                                    |
| E          | removeLast()  | 移除并返回此列表的最后一个元素                                  |
| E          | peekFirst()   | 获取但不移除此列表的第一个元素（链表为空，返回 null）           |
| E          | pollFirst()   | 获取但不移除此列表的第一个元素（列表为空，返回 null）           |

### 1.3、Vector 集合的特点及方法（被 ArrayList 取代）

> 特点：数据存储的结构是数组结构，为 JDK 中最早提供的集合。Vector 集合已被 ArrayList 替代。枚举 Enumeration 已被迭代器 Iterator 替代。

## 二、Set 接口

> Set 接口通常表示一个集合，其中的元素不允许重复（通过 hashcode 和 equals 函数保证），常用实现类有 HashSet 和 TreeSet，HashSet 是通过 Map 中的 HashMap 实现的，而 TreeSet 是通过 Map 中的 TreeMap 实现的。另外，TreeSet 还实现了 SortedSet 接口，因此是有序的集合（集合中的元素要实现 Comparable 接口，并覆写 Compartor 函数才行）。
>
> Set 接口子实现类的特点
>
> * HashSet：内部数据结构是哈希表（线程不安全）
> * LinkHashSet：内部数据结构是链表和哈希表（线程不安全）
> * TreeSet：内部数据结构是平衡树（Balanced tree），元素唯一、有序（线程不安全）

**提示**

实体类使用 Set 集合时，最好重写 hashCode()、equals()方法，保证 Set 集合元素唯一性

java 中判断对象是否相同时，判断步骤如下

1. 判断的是两个元素的哈希值是否相同，即 hashCode()
2. 如果哈希值不同，不需要判断 equals()，就可以保证元素的唯一了
3. 如果相同，再判断两个对象的内容是否相同，即 equals()

**注意**：hashCode()方法判断对象的哈希值是否相同；equals()方法判断内容是否相同

**注意**：HashSet 存储 JavaAPI 中提供的类型元素时，不需要重写元素的 hashCode()和 equals()方法，因为这两个方法，在 JavaAPI 的每个类中已经重写，如 String 类、Integer 类等，但是自定义类需要自己重写 hashCode()和 equals()方法，否则无法保证元素唯一性。

### 2.1、HashSet 的特点及方法

特点：数据存储的结构是哈希表。元素存取无序，集合元素唯一，元素并不是按照存入时的顺序（和 List 显然不同） 是按照哈希值确定存放在 HashSet 集合的位置，因此也是按照哈希值取数据的

常用方法：全部实现自 Set 接口

### 2.2、LinkHashSet 的特点及方法

特点：链表和哈希表组合的一个数据存储结构，因此元素存取有序、且保证元素唯一性

常用方法：全部实现自 Set 接口

### 2.3、TreeSet 的特点及方法

特点：TreeSet 集合的底层是二叉树进行排序的，集合元素唯一性

常用方法：

* TreeSet 判断元素唯一性的方式：根据比较方法的返回结果判断，是 0，就是相同元素；不是 0，元素不相同

* TreeSet 对元素进行排序的方式

元素自身具备比较性：元素实现 Comparable 接口，重写 compareTo 方法
容器具备比较性：使用带参构造创建 TreeSet(Collection\<? extends E> c) ，实现 compare(T o1, T o2)方法
注意：当 Comparable 比较方式和 Comparator 比较方式同时存在时，以 Comparator 的比较方式为主。

## 三、Map 接口

Map 用于保存具有映射关系的数据，总是以键值对的方式存储数据。

Map 集合的 key 和 value 都可以是任何引用类型的数据。Map 集合的 key 不允许重复，value 允许重复。key 和 value 之间存在单向一对一关系，即通过指定的键可以找到唯一，确定的 value。Map 集合中获取数据时，只要给出指定的 key，就可以取出对应的 value。

常用方法：

| 返回值类型 | 方法                            | 解释                                                                               |
| ---------- | ------------------------------- | ---------------------------------------------------------------------------------- |
| void       | clear()                         | 删除该 Map 对象中所有键值对。                                                      |
| boolean    | containsKey(Object key)         | 查询 Map 中是否包含指定的 key 值。                                                 |
| boolean    | containsValue(Object value)     | 查询 Map 中是否包含一个或多个 value。                                              |
| Set        | entrySet()                      | 返回 map 中包含的键值对所组成的 Set 集合，每个集合都是 Map.Entry 对象。            |
| Object     | get()                           | 返回指定 key 对应的 value，如果不包含 key 则返回 null。                            |
| boolean    | isEmpty()                       | 查询该 Map 是否为空。                                                              |
| Set        | keySet()                        | 返回 Map 中所有 key 组成的集合。                                                   |
| Collection | values()                        | 返回该 Map 里所有 value 组成的 Collection。                                        |
| Object     | put(Object key,Object value)    | 添加一个键值对，如果集合中的 key 重复，则覆盖原来的键值对。                        |
| void       | putAll(Map m)                   | 将 Map 中的键值对复制到本 Map 中。                                                 |
| Object     | remove(Object key)              | 删除指定的 key 对应的键值对，并返回被删除键值对的 value，如果不存在，则返回 null。 |
| boolean    | remove(Object key,Object value) | 删除指定键值对，删除成功返回 true。                                                |
| int        | size()                          | 返回该 Map 里的键值对个数。                                                        |

### 3.1、HashMap

> 底层是**哈希表数据结构**。
>
> **特点**：允许使用 null 值和 null 键，该集合是线程不同步的，JDK1.2 出现，效率高。

常用方法：全部实现自 Map 接口

### 3.2、LinkHashMap

> LinkedHashMap 是 HashMap 的子类，但是内部还有一个双向链表维护键值对的顺序，每个键值对既位于哈希表中，也位于双向链表中。
>
> **LinkedHashMap 通过维护一个运行于所有条目的双向链表 ,保证了元素迭代的顺序**。**该迭代顺序可以是插入顺序或者是访问顺序。**

常用方法：全部实现自 Map 接口

### 3.3、TreeHashMap

> 底层是**二叉树(红黑树)数据结构**。
>
> **特点**：线程不同步，可以同时给 Map 集合中的键进行排序。

常用方法：全部实现自 Map 接口

### 3.4、HashTable

> 底层是**哈希表数据结构**。
>
> **特点**：不可以存入 null 键 null 值，该集合是线程同步的，JDK1.0 出现，效率低。

常用方法：全部实现自 Map 接口
