# java 集合总结
Java 集合工具包位于 Java.util 包下,包含了很多常用的数据结构,如数组、链表、栈、队列、集合、哈希表等。学习 Java 集合框架下大致可以分为如下五个部分:List列表、Set集合、Map映射、迭代器(Iterator、Enumeration)、工具类(Arrays、Collections)。
# java 集合接口继承体系图
Java 集合类的整体框架如下:
从上图中可以看出,集合类主要分为两大类: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 中判断对象是否相同时,判断步骤如下
- 判断的是两个元素的哈希值是否相同,即 hashCode()
- 如果哈希值不同,不需要判断 equals(),就可以保证元素的唯一了
- 如果相同,再判断两个对象的内容是否相同,即 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 接口