前言
Java集合框架概述; 主要总述Java集合框架的设计理念, 组成和基本接口(及其区别等)
Java集合框架系列博客:
正文
一. 设计理念
-
在Java 2之前,Java是没有完整的集合框架的。它只有一些简单的可以自扩展的容器类,比如Vector,Stack,Hashtable等)
-
Java集合其实就是一组对象的集合
-
独立于实现细节, 方便重用, 保证向下兼容(即保留了
Vector等旧的API) -
加强了API之间的互通信, 减少了新API的学习: 提供尽量统一的接口
二. 基本组成
2.1 总述
Java集合框架主要分为三个部分: 接口, 实现和算法
2.1-1 接口
接口指的是以Collection和Map为起始的一系列公用接口
实际上从Map出发的并不是真正的集合, 只是其包含集合视图操作, 所以也将其归入集合框架中
从Collection出发的公用接口主要有以下几个, 也是这次会着重讲解和比较的; 当然, 下面的接口并不全面, 在后面会逐渐扩展和补充

从Map出发的公用接口如下

当然, 上述列举出来的子接口都是直接继承自Collection或者Map, 对于其子接口的子接口, 这里并没有列出在这里(比如NavigableMap接口是SortedMap接口的子接口, 而不是直接继承Map的, 所以这里并没有直接列出来)
2.1-2 实现
实现指的是接口的实现类, 这里笔者在官网找到一张表, 如下, 很好的列出了平时重点所用的实现类
| Interface | Hash Table | Resizable Array | Balanced Tree | Linked List | Hash Table + Linked List |
|---|---|---|---|---|---|
| Set | HashSet | TreeSet | LinkedHashSet | ||
| List | ArrayList | LinkedList | |||
| Deque | ArrayDeque | LinkedList | |||
| Map | HashMap | TreeMap | LinkedHashMap |
当然, 还应该包含Java 2以前几个旧API, 即: Vector, Stack, Hashtable
2.1-3 算法
(1). 算法
算法指的是以Collections为主的提供的一系列对集合的操作, 参见下图, 列出了其提供的常用算法

下面对上述方法进行一些简单解释
-
sort(List): 使用归并排序, 保证NlogN的时间复杂度和稳定性 -
binarySearch(List, Object): 在一个有序的List中使用二分查找 -
reverse(List): 逆转List -
shuffle(List): 将List中的元素随机重排 -
fill(List, Object): 使用指定值(Object)覆盖List中所有元素 -
copy(List dest, List src): 拷贝 -
min(Collection): 返回最小值 -
max(Collection): 返回最大值 -
rotate(List list, int distance): 将List中元素旋转指定distance -
replaceAll(List list, Object oldVal, Object newVal): 将List中出现的所有oldVal替换为newVal -
indexOfSubList(List source, List target): 返回source中与target匹配的第一个子项的首元素索引 -
lastIndexOfSubList(List source, List target): 返回最后一个匹配子项的首元素索引 -
swap(List, int, int): 交换指定位置的两个元素 -
frequency(Collection, Object): 找出指定元素出现次数 -
disjoint(Collection, Collection): 判断两个集合是否包含相同元素(即集合是否相交) -
addAll(Collection<? super T>, T...): 将指定元素添加到指定集合中
(2). 包装类
当然, 实际上Collections提供的不仅仅是针对集合的算法, 其还提供了一系列对集合的包装类(即Wrapper), 主要包括以下三大类:
-
Collections.unmodifiableInterface(): 返回一个不可修改的集合, 包括UnmodifiableCollection,UnmodifiableSet,UnmodifiableList; 实现原理是在修改集合的操作上(如add(),remove()等)抛出异常 -
Collections.synchronizedInterface(): 返回一个线程安全的集合, 包括SynchronizedCollection,SynchronizedSet,SynchronizedList; 实现原理是在需要同步的方法上添加synchronized限制 -
Collections.checkedInterface(): 返回一个类型检查的集合, 包括CheckedCollection,CheckedQueue,CheckedSet,CheckedList; 实现原理是在add()的时候进行类型检查, 如果是非法类型, 就抛出异常ClassCastException; 这里的类型检查实际上是使用Class.isInstance()来检查的, 关于该方法和instanceof运算符的区别, 参见博客; (大致上, 二者是等价的, 只是isInstance()是在运行时才进行类型检查, 故可用于反射, 泛型; 但是instanceof需要在编译时知道类的具体类型(重点理解在动态等价))
这些包装类的作用主要是满足平时一些特殊的需求, 比如同步, 不可修改等
三. 基本接口
在这一节, 主要讲解上面提到的几个基本接口, 这里不会涉及到其实现类
3.1 Collection
Collection是集合框架中一个最顶层的基本接口, 提供了一个数据集的基本描述, 在官方API中并没有提供其直接实现类, 而是在其基础上提供了进一步的限制接口, 即List, Set, Queue; 这样做的好处有:
-
代码复用: 从面向对象的角度讲, 抽取出一个顶级接口, 有助于用户代码复用, 即编写一个接口, 实现不同传参(
Collection的各种实现类), 实际上也是利用了多态(官方文档的解释是: 实现最大通用性) -
易于扩展: 符合面向对象的思想, 即将数据集抽象, 通过不同的需求对其实现不同方便的限制, 易于扩展; 同时减少新API学习成本
Collection提供了数据操作的基本方法, 如add(), remove(), size(), clear()等; 同时, 其还继承了Iterable接口, 这个接口是用于使用迭代器遍历集合用的, 使用迭代器遍历集合的优点是我们不必知道集合的内部结果,集合的内部结构、状态由Iterator来维持, 通过统一的方法hasNext(), next()来判断和获取下一个元素
3.2 List
List在Collection上做的限制是, 元素有序(但并不是排序), 允许重复元素; 同时还将迭代器换成了ListIterator; 关于ListIterator, 其允许双向的迭代, 以及元素插入(ListIterator.add()), 删除(ListIterator.remove())和替换ListIterator.set()
在JDK9中, 还提供了一个List.of()的静态方法, 用于返回一个不可变List(Immutable List)
3.3 Set
Set在Collection上做的限制是, 元素不重复, 至多一个null元素
在JDK9中, 还提供了一个Set.of()的静态方法, 用于返回一个不可变的Set
3.4 Queue
Queue在Collection上做的限制是, 除了Collection提供的基本操作外, 还提供了一些额外的操作, 分为两类, 一个返回特定值, 另一个抛出异常, 见下表
| Throw Exception | Return Special Value | |
|---|---|---|
| Insert | add(e) | offer(e) |
| Remove | remove() | poll() |
| Examine | element() | peek() |
3.5 Map
Map本质上是一组键值对, Map允许单独访问key(通过keySet()返回key的Set), 也可以单独访问value(通过values()方法返回value的Collection), 也可以通过entrySet()获取key-value的对应关系