# java 集合总结

Java 集合工具包位于 Java.util 包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。学习 Java 集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(IteratorEnumeration)、工具类(ArraysCollections)。

# java 集合接口继承体系图

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

接口

从上图中可以看出,集合类主要分为两大类:CollectionMap

CollectionListSet等集合高度抽象出来的接口,它包含了这些集合的基本操作,它主要又分为两大部分:ListSet

# 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 接口