Java 集合

Java 集合类用于存储对象,可以实现常用的数据结构。

一、集合概述

1. 什么是集合?

集合类又称容器类,主要用于保存数据。

2. 集合类与数组的区别

  • 数组:

    • 长度固定

    • 元素既可以是基本类型,也可以是引用类型

    • 只能存储同一类型的数据

  • 集合类:

    • 长度可变
    • 元素仅能是引用类型(的指针)
    • 可以存储不同类型数据

3. 集合的分类

集合可以分为两大类:

  • Collection:用于存储数量不等的数据

    • List:有序、可重复的列表

      • ArrayList:基于动态数组实现;支持随机访问
      • Vector:与 ArrayList 类似,但线程安全
      • LinkedList:基于双向链表实现;只能顺序访问
    • Set:无序、不可重复的集合

      • TreeSet:基于红黑树实现;支持 o(logN) 级查找;支持有序性操作

      • HashSet:基于哈希表实现;支持 o(1) 级查找;不支持有序性操作

      • LinkedHashSet:与 HashSet 相比,支持了有序性操作

    • Queue:队列

      • ArrayDeque:基于循环数组实现
      • PriorityQueue:基于堆实现;可以作为优先队列
  • Map:用于储存键值对

    • HashMap:基于哈希表实现

    • LinkedHashMap:与 HashMap 相比,维护了键的顺序

    • TreeMap:基于红黑树实现

    • Hashtable:与 HashMap 类似,但线程安全;遗留类,不应再使用

    • ConcurrentHashMap:线程安全,且效率更高

      引入了分段锁

二、Collection

1. 什么是 Collection?

Collection 接口是 List、Set、Queue 接口的父接口,该接口中的方法可以用于操作 List、Set、Queue 集合。

2. 集合方法

Collection 接口中有以下方法:

方法 说明
add(Object obj) 向集合中添加指定元素
remove(Object obj) 从集合中删除指定元素
clear() 清空集合所有元素
contains(Object obj) 判断集合中是否有指定元素
isEmpty() 判断集合是否为空
iterator() 返回一个 Iterator 对象,用于遍历集合
size() 返回集合的元素个数
toArray() 将集合以数组形式返回

三、Collections

1. 说明

Collections 是一个用于操作 Set、List、Map 等集合的工具类,该工具类中提供了对于集合的操作方法。

2. 对 List 的方法

方法 说明
reverse(list) 反转 list 中元素的顺序
shuffle(list) 对 list 中的元素进行随机排序
sort(list[, comparator]) 对 list 进行自然排序或指定排序
swap(List, index1, index2) 将 list 中 index1 和 index2 的元素进行交换
rotate(list, distance) 当 distance 为正时,将后 distance 个元素移到前面;当 distance 为负时,将前 distance 个元素移到后面
binarySearch(list, obj) 用二分法查找指定元素,要求 list 有序
fill(list, obj) 用指定元素填满 list
indexOfSubList(list, subList) 返回 subList 在 list 中第一次出现的位置
lastIndexOfSubList(list, subList) 返回 subList 在 list 中最后一次出现的位置
replaceAll(list, oldVal, newVal) 用 newVal 替换 list 中的 oldVal

3. 对 Collections 的方法

方法 说明
max(collection[, comparator]) 根据自然排序或指定排序,返回 collection 中的最大元素
min(collection[, comparator]) 根据自然排序或指定排序,返回 collection 中的最小元素
frequency(collection, obj) 返回 obj 在 collection 中的出现次数

4. synchronizedXxx()

Collections 类中提供了多个 synchronizedXxx() 方法,用于将指定集合包装成线程同步的集合,从而可以解决多线程并发访问集合时的线程安全问题。

1
Xxx 集合名 = Collections.synchronizedXxx(非同步集合);
1
2
3
4
5
6
7
public class Test {
public static void main(String[] args) {
List list = Collections.synchronizedList(new ArrayList());
Set set = Collections.synchronizedSet(new HashSet());
Map map = Collections.synchronizedMap(new HashMap());
}
}

5. 不可变集合

(1) 常用方法

Collections 提供了用于获取不可变集合的方法。

方法 说明
emptyXxx() 返回一个空的、不可变的集合
singletonXxx(obj) 返回一个只包含指定对象、不可变的集合
unmodifiableXxx(collection) 返回指定集合的不可变版本

(2) Java 9 新增

可以通过类方法 of(obj, obj, ···, obj) 创建具有若干个指定元素的不可变集合。

1
Xxx 集合名 = Xxx.of(obj, obj, ···, obj);
1
2
3
List list = List.of(obj, obj, ···, obj);
Set set = Set.of(obj, obj, ···, obj);
Map map = Map.of(obj, obj, ···, obj);

四、迭代器

1. 什么是迭代器?

Iterator,又称为迭代器,可以用于遍历实现了 Iterable 接口的对象。

2. 说明

方法 说明
hasNext() 判断是否有下一个元素
next() 返回集合中下一个元素
remove() 删除上一个 next() 返回的元素
forEachRemaining(Consumer action) 用 Lambda 表达式遍历集合
1
2
3
4
Iterator iterator = 集合名.iterator();
while (iterator.hasNext()) {
···iterator.next()···
}

五、Stream 流

1. 什么是 Stream 流?

Stream 流是 Java8 中添加了一个新的接口类,相当于高级版的 Iterator。

Stream 流将元素集合看作一种流,通过一系列处理得到最终的结果。

2. 创建 Stream 流

(1) 直接创建

创建 Stream 的 builder,再通过 add() 方法增加元素,最后调用 build() 方法创建 Stream 流。

1
Stream.builder().add(元素).add(元素) ··· .add(元素).build()

(2) 通过 Collection 创建

1
Collection实例.stream()

(3) 通过 Map 创建

首先通过 Map 的方法获得 Collection实例,然后再创建 Stream 流。

1
2
3
4
5
6
7
8
// 所有key组成的集合
Map实例.keySet().stream()

// 所有value组成的集合
Map实例.values().stream()

// 所有键值对组成的集合
Map实例.entrySet().stream()

(4) 通过数组创建

通过 Stream 的静态方法 of() 创建

1
Stream.of(数组)

3. 处理 Stream 流

方法 说明
filter(Predicate predicate) 过滤所有不符合 predicate 的元素
limit(long maxSize) 只保留前 maxSize 个元素
skip(long discardNum) 丢弃前 discardNum 个元素
concat(Stream stream1, Stream stream2) 合并 stream1 和 stream2
distinct() 过滤,相同的元素只保留一个
sorted([Comparator comparator]) 排序,自然排序或通过 comparator 排序
map(Function function) 返回将 function 应用于每个元素之后的 Stream 流

4. 终结 Steam 流

调用以下方法后,Stream 流将终结。

方法 说明
foreach(Consumer consumer) 遍历元素,对每个元素执行 consumer
toArray() 转换为数组
count() 返回流中的元素个数

5. 示例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class Student {
private String name;
private int score;

// 构造方法

// get方法

// equals()和hashCode()

// toString()方法
}

public class Test {
public static void main(String[] args) {
ArrayList<Student> arrayList = new ArrayList<>();
arrayList.add(new Student("小王", 100));
arrayList.add(new Student("小王", 100));
arrayList.add(new Student("小王", 100));
arrayList.add(new Student("小李", 94));
arrayList.add(new Student("小张", 97));
arrayList.add(new Student("小笨", 60));
arrayList.add(new Student("小坏", 0));
arrayList.stream()
.filter((Student student) -> student.getScore() >= 60)
.distinct()
.forEach(System.out::println);
}
}

六、List

具体请看:

Java 集合-List

七、Queue

具体请看:

Java 集合-Quque

八、Map

具体请看:

Java 集合-Map

九、Set

具体请看:

Java 集合-Set

参考