两万字长文读懂 Java 集合


两万字长文读懂 Java 集合

文章插图
作者 | 小菠萝
来源 | JAVA建设者(ID:javajianshe)
这篇文章历经过 5 次的打磨和修复,只为把最好的文章为大家分享 。
集合在我们日常开发使用的次数数不胜数,ArrayList / LinkedList / HashMap / HashSet……信手拈来,抬手就拿来用,在 IDE 上龙飞凤舞,但是作为一名合格的优雅的程序猿,仅仅了解怎么使用 API 是远远不够的,如果在调用 API 时,知道它内部发生了什么事情,就像开了透视外挂一样,洞穿一切,这种感觉才真的爽,而且这样就不是集合提供什么功能给我们使用,而是我们选择使用它的什么功能了 。
两万字长文读懂 Java 集合

文章插图
两万字长文读懂 Java 集合

文章插图
集合框架总览
下图堪称集合框架的上帝视角,讲到集合框架不得不看的就是这幅图,当然,你会觉得眼花缭乱,不知如何看起,这篇文章带你一步一步地秒杀上面的每一个接口、抽象类和具体类 。我们将会从最顶层的接口开始讲起,一步一步往下深入,帮助你把对集合的认知构建起一个知识网络 。
两万字长文读懂 Java 集合

文章插图
工欲善其事必先利其器,让我们先来过一遍整个集合框架的组成部分:
  1. 集合框架提供了两个遍历接口:Iterator 和 ListIterator,其中后者是前者的优化版,支持在任意一个位置进行前后双向遍历 。注意图中的 Collection 应当继承的是 Iterable 而不是 Iterator,后面会解释 Iterable 和 Iterator 的区别 。
  2. 整个集合框架分为两个门派(类型):Collection 和 Map,前者是一个容器,存储一系列的对象;后者是键值对 <key, value>,存储一系列的键值对 。
  3. 在集合框架体系下,衍生出四种具体的集合类型:Map、Set、List、Queue 。
  4. Map 存储 <key,value> 键值对,查找元素时通过 key 查找 value 。
  5. Set 内部存储一系列不可重复的对象,且是一个无序集合,对象排列顺序不一 。
  6. List 内部存储一系列可重复的对象,是一个有序集合,对象按插入顺序排列 。
  7. Queue 是一个队列容器,其特性与 List 相同,但只能从队头和队尾操作元素 。
  8. JDK 为集合的各种操作提供了两个工具类 Collections 和 Arrays,之后会讲解工具类的常用方法 。
  9. 四种抽象集合类型内部也会衍生出许多具有不同特性的集合类,不同场景下择优使用,没有最佳的集合 。
上面了解了整个集合框架体系的组成部分,接下来的章节会严格按照上面罗列的顺序进行讲解,每一步都会有承上启下的作用 。
学习Set前,最好最好要先学习 Map,因为 Set 的操作本质上是对 Map 的操作,往下看准没错
 
Iterator Iterable ListIterator在第一次看这两个接口,真以为是一模一样的,没发现里面有啥不同,存在即合理,它们两个还是有本质上的区别的 。
首先来看 Iterator 接口:
 public interface Iterator<E> {booleanhasNext;E next;voidremove;}提供的 API 接口含义如下:
  • hasNext:判断集合中是否存在下一个对象
  • next:返回集合中的下一个对象,并将访问指针移动一位
  • remove:删除集合中调用 next 方法返回的对象
在早期,遍历集合的方式只有一种,通过 Iterator 迭代器操作:
 List<Integer> list = new ArrayList<>;list.add(1);list.add(2);list.add(3);Iterator iter = list.iterator;while (iter.hasNext) {Integer next = iter.next;System.out.println(next);if (next == 2) { iter.remove; }}再来看 Iterable 接口:
 public interface Iterable<T> {Iterator<T> iterator;// JDK 1.8default voidforEach(Consumer<? super T> action) {Objects.requireNon(action);for (T t : this) {action.accept(t);}}}可以看到 Iterable 接口里面提供了 Iterator 接口,所以实现了 Iterable 接口的
集合依旧可以使用迭代器遍历和操作集合中的对象;
而在 JDK 1.8中,Iterable 提供了一个新的方法 forEach,它允许使用增强for 循环遍历对象 。
 List<Integer> list = new ArrayList<>;for (Integer num : list) {System.out.println(num);}我们通过命令:javap -c 反编译上面的这段代码后,发现它只是 Java 中的一个语法糖,本质上还是调用 Iterator 去遍历 。


推荐阅读