JAVA集合源码攻坚战(1)——Iterator
前言
工作了两年了,对JAVA集合框架部分,只知道怎么用,却不知道原理,不能说是一个合格的java程序员,深感知识的缺乏,所以趁最近有空,进行JAVA集合攻坚战,学习JAVA集合部分的源码,以jdk 1.8为准。
整个JAVA集合框架的概图
这里先看一张取自菜鸟教程的java集合框架图
菜鸟教程的这张图已经包括了大部分类和接口之间的关系,不过还有一些遗漏的,而且也没有很好的表示出继承或实现的关系。后面等整个框架的所有体系都看完了,再自己总结一张图吧。
整体概述
从上面的图中,Java 集合框架主要包括两种类型的容器,一类是Collection,存储一个元素集合,另一类是Map,存储键值对映射。
集合框架是一个用来代表和操纵集合的统一架构。所有的集合框架都包含如下内容:
接口:是代表集合的抽象数据类型。例如 Collection、List、Set、Map 等。之所以定义多个接口,是为了以不同的方式操作集合对象
实现(类):是集合接口的具体实现。从本质上讲,它们是可重复使用的数据结构,例如:ArrayList、LinkedList、HashSet、HashMap。
算法:是实现集合接口的对象里的方法执行的一些有用的计算,例如:搜索和排序。这些算法被称为多态,那是因为相同的方法可以在相似的接口上有着不同的实现。
学习过程
根据图中来看,我们从左上角开始,剥洋葱一样一层层的往下剥 []( ̄▽ ̄)*~
Iterator
今天首先来看Iterator,这是一个接口类,位于上图的最左侧顶点,提供了整个集合框架的各个实现类一个遍历的算法实现。
从jdk1.2开始,它的出现替代了原来的Enumeration类,
我们先来看Enumeration类的源码:
public interface Enumeration<E> {
/**
* Tests if this enumeration contains more elements.
*
* @return <code>true</code> if and only if this enumeration object
* contains at least one more element to provide;
* <code>false</code> otherwise.
*/
boolean hasMoreElements();
/**
* Returns the next element of this enumeration if this enumeration
* object has at least one more element to provide.
*
* @return the next element of this enumeration.
* @exception NoSuchElementException if no more elements exist.
*/
E nextElement();
}
可以看出,Enumeration类只有两个方法,
- hasMoreElements() // 是否还有更多元素
- nextElement() //下个元素
不过根据官方文档,推荐使用Iterator接口。
NOTE: The functionality of this interface is duplicated by the Iterator interface. In addition, Iterator adds an optional remove operation, and has shorter method names. New implementations should consider using Iterator in preference to Enumeration.
这里就不纠结于原因了。
Iterator源码分析
在jdk1.8 之前,Iterator接口提供了三个方法:
- boolean hasNext() // 判断是否有下个元素
- E next() //返回下一个元素
- default void remove() // 删除集合里上一次调用next()方法返回的那个元素
这里需要注意的是,remove()方法必须在迭代过程中,调用过next()方法后才能调用,且每次调用next()方法后,只允许调用remove()方法最多一次,不然会抛出异常。
而对于jdk1.8 ,还增加了一个默认方法
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
该方法可以使得调用者能够通过lambda表达式来遍历元素,可以在遍历时,对每次遍历的对象进行操作。
总结
总之,Iterator接口为整个集合类提供了一个遍历元素的方法,使用迭代器的方式,能够让我们不用关心集合内的数据的具体类型。