目录
- 1. 什么是集合?
- 2. 为什么要使用集合?
- 3. 3个接口介绍
- 3.1 `List` 接口包括以下实现
- 3.2 `Set` 接口包括以下实现
- 3.3 `Map` 接口包括以下实现
- 4. 如何选择集合?
- 5. 比较和区别一些接口或类
- 6. Collections 工具类有哪些常用方法?
- 6.1 排序
- 6.2 查找,替换
1. 什么是集合?
集合类是 Java 数据结构的实现。它允许以各种方式将元素分组,并定义了各种使这些元素更容易操作的方法。集合类是可以往里面保存多个对象的类,存放的是对象,不同的集合类有不同的功能和特点,适合不同的场合,用以解决一些实际问题。
Java中的集合类可以分为两大类:一类是实现Collection接口;另一类是实现Map接口。
Collection
是一个基本的集合接口,Collection
中可以容纳一组集合元素(Element)。Map
没有继承Collection
接口,与Collection
是并列关系。Map提供键(key)到值(value)的映射。一个Map
中不能包含相同的键,每个键只能映射一个值。
Collection
有两个重要的子接口 List
和 Set
。List
是一个有序的集合,其中的每个元素都有索引,使用此接口能够准确的控制每个元素插入的位置。Set
接口的特点是不能包含重复的元素,最多有一个 null 元素。
在 Java 中,以 Map
结尾的类都实现了 Map
接口。除了以 Map
结尾的类之外, 其他类都实现了 Collection
接口。
2. 为什么要使用集合?
- 增加代码重用性。
- 提升程序的运行速度和质量。
- 降低编程难度。
3. 3个接口介绍
List, Set, Map 的区别
-
List
:存储的元素是有序的、可重复的。 -
Set
:存储的元素是无序的,不可重复的。 -
Map
:使用键值对(Key-Value
)存储。Key
是无序的、不可重复的。
3.1 List
接口包括以下实现
-
ArrayList
:Object[]
类型的数组。适用于频繁的查找,线程不安全。 -
Vector
:Object[]
类型的数组。线程安全。 -
LinkedList
:双向链表。适用于添加、删除。
3.2 Set
接口包括以下实现
-
HashSet
:基于HashMap
实现,底层采用HashMap
保存元素。 -
LinkedHashSet
:LinkedHashSet
是HashSet
的子类,其内部是通过LinkedHashMap
实现的。 -
TreeSet
:是有序的、唯一的。通过红黑树(自平衡的排序二叉树)实现。
3.3 Map
接口包括以下实现
-
HashMap
:底层是基于拉链式散列结构(也就是数组和链表)或红黑树组成。当链表长度大于某一阈值(默认为8)时,会转换成红黑树,以减少搜索时间。如果当前数组的长度小于64,先进行数组扩容,而不是直接转换为红黑树。 -
LinkedHashMap
:LinkedList
继承于HashMap
,所以它的底层是在HashMap
结构的基础上,增加了一条双向链表,使得HashMap
结构可以保持键值对的插入顺序。同时,通过堆链表进行相应的操作,实现了访问顺序的相关逻辑。 -
HashTable
:由数组+链表组成,数组是HashMap
的主体, 链表是为了解决哈希冲突。 -
TreeMap
:红黑树(自平衡的二叉排序树)。
4. 如何选择集合?
根据集合的特点选取,比如,
- 根据键值获取元素值:
Map
下的接口 - 需要排序:
TreeMap
- 不需要排序:
HashMap
- 需要保证线程安全:
ConcurrentHashMap
- 只需要存放元素值:实现
Collection
接口的集合 - 需要保证元素唯一:实现
Set
接口的集合,如HashSet
或TreeSet
- 不需要保证元素唯一:实现
List
接口的集合,如ArrayList
或LinkedList
5. 比较和区别一些接口或类
1)比较 ArrayList
, LinkedList
, Vector
ArrayList | LinkedList | Vector | |
底层数据结构 | Object[] 数组 | 双向链表 | Object[] 数组 |
是否保证线程安全 | 不保证 | 不保证 | 保证 |
是否支持随机访问 | get(index) | 不支持 | get(index) |
内存空间占用 | 结尾预留一定的容量空间 | 每个元素比ArrayList的空间多 | 结尾预留一定的容量空间 |
2)比较 Collection
接口中的 Comparable
, Comparator
接口 | Comparable | Comparator |
包 | java.lang | java.util |
排序的方法 | compareTo(Object obj) | compare(Object obj1, Object) obj2) |
怎么自定义排序 | 重写compareTo() | 自制 Comparator |
自制 Comparator
Comparator<Integer> comparator = new Comparator<Integer>(){
public int compare(int a, int b) {
return b-a;
}
}
重写 compareTo()
public class Person implements Comparable<Person> {
private int age;
Person(){}
// 重写compareTo()
public int compareTo(Person p) {
if (this.age>p.age) return 1;
if (this.age<p.age) return -1;
return 0;
}
}
3)比较 HashSet
, LinkedHashList
, TreeSet
HashSet | LinkedHashSet | TreeSet | |
底层 | HashMap | HashSet的子类 | 红黑树 |
是否有序 | 无序 | 有序 | 有序 |
线程是否安全 | 不安全,可以存 null 值 | 不安全 | 不安全 |
遍历 | — | 按照添加的顺序 | 按照添加的顺序 |
排序 | — | — | 自然排序、定制排序 |
4)比较 HashMap
和 HashTable
HashMap | HashTable | |
线程是否安全 | 不安全 | 安全 |
效率 | 较高 | 基本被淘汰 |
是否支持 Null Key 和 Null Value | Key 为空的只能有一个,Value 为空的可以有多个 | 不允许有空Key 和 空 Value,会抛出异常 |
初始容量 | 16/或者给定的大小) | 11 |
扩充容量 | 变为原来的2倍/扩充为2的幂次方 | 变为原来的 2n+1 |
5)比较 HashMap
和 HashSet
类 | HashMap | HashSet |
实现的接口 | Map | Set |
底层 | 基于拉链式散列结构 | HashMap |
存储对象 | 键值对 | 仅存储对象 |
添加元素的方法 | put() | add() |
计算哈希码 | 使用键Key计算Value | 两个成员的哈希码可以相同,用equals()判断对象是否相等 |
6)比较 HashMap
和 TreeMap
类 | HashMap | TreeMap |
父类 | AbstractMap | AbstractMap |
实现的接口 | — | NavigableMap 和 SortedMap |
搜索 | — | 对集合内元素搜索 |
排序 | — | 对集合内的元素根据键排序,默认升序 |
7)比较 == 和 equals
== | equals | |
基本类型 | 值是否相等 | — |
引用类型 | 两个引用是否指向同一个对象地址 | 没有被重写:比较的是地址是否相等。被重写(如String):比较的是地址里的内容。 |
6. Collections 工具类有哪些常用方法?
6.1 排序
void reverse(List list); // 反转
void sort(List list); // 按自然排序的升序排序
void swap(List list, int i, int j); // 交换两个索引位置的元素
// 旋转。distance>0,把list后distance个元素整体移到前面。distance<0,把list前distance个元素整体移到后面。
void rotate(List list, int distance);
6.2 查找,替换
int binarySearch(List list, Object key); // 对list进行二分查找,返回索引
int max(Collection coll); // 根据元素的自然顺序,返回最大的元素
int max(Collection coll, Comparator c); // 根据定制顺序,返回最大的元素
boolean replaceAll(List list, Object oldVal, Object newVal); // 用新元素替换旧元素
参考链接: