时间: 2021年9月26日星期日 小雨
题目
大家好,我是小崔爱读书,本期要说的是《2020年Java面试208题》的第18题。
面试官问了这样一个问题: 请说说 Iterator ListIterator 和 Spliterator 的区别。
知识点分析
这三个都是迭代器,答题的时候一定要讲讲迭代器模式。
ListIterator其实放在这里是凑数的,它没什么高级功能,就是一种特殊的迭代器而已。
Spliterator迭代器支持并行,可以充分发挥多核CPU的性能,这个比较厉害。因此要好好说说Spliterator的特性,这个比较提高逼格。
好的,面试的时候说到上面这些点,就够了。
演示面试
接下来就由我来进行演示面试。
您好,面试官。
这三个东西核心都是迭代器,最基础的就是Iterator 接口,这是一个通用迭代器; ListIterator 是针对List 数据结构的迭代器; Spliterator 是支持并行的迭代器。
迭代器模式
说到迭代器就不能不提一下迭代器模式,这是一种设计模式,提出迭代器设计模式的缘由是因为架构师们认为在对集合进行遍历的时候,应该只关心对元素的遍历,而不关心具体的元素。假如用下标遍历的话,是需要关心元素的数量的,而遍历其实应该与元素数量、元素类型、元素顺序等等都没关系,遍历应该是单纯的遍历。基于这个思想,提出了迭代器模式。
Iterator是最常用的迭代器
如迭代器模式定义的,Iterator这个类定义了遍历集合的方法,而不关心集合是什么类型的、也不关心集合中的元素的类型。
Iterator定义了一个游标指向元素中的某个元素,并且可以不停的移动到下一个元素,通过这种方式实现了集合的遍历。
Iterator使用 hasNext 方法判断是否还有下一个元素,使用 next 方法移动游标并获取下一个元素。
Iterator 可以使用 remove 方法将当前的元素从集合中移除。
所有这些方法都是迭代器模式定义的规范。
Iterator是Java程序员很常见的接口,我就不多说了。
ListIterator是针对List的特殊迭代器
ListIterator继承自Iterator接口,它也是一个接口。
ListIterator只针对List进行迭代,由于知道其迭代的集合是List的,所以,ListIterator提供了很多更有针对性的方法。
比如向前、向后迭代等等,这点儿就比Iterator强大,Iterator只能向后移动,不能向前移动游标。
还可以获取下一个元素的索引,也可以获取前一个元素的索引,这也是由于针对的是List才可以定义的方法,因为List是很明确有索引这个概念的,因此ListIterator就可以定义索引相关的方法。
ListIterator也不复杂,就不多说了。
Spliterator则是强大的,为并行计算而生的迭代器
Spliterator在设计思想上可以说完全是革命性的,与前两个迭代器几乎不是一回事。
因为这个东西除了迭代这个功能之外,更重要的特性是为并行计算而生。
咋说是为并行计算而生呢?这个Spliterator可以将集合的迭代器,分拆成多个小迭代器。比如,迭代器中元素总共有1万个,分拆一次,成两个迭代器A和B了,分别有元素 5000个,再继续拆分成A、B、C、D 4个迭代器,分别有 2500 个元素。再一步步拆分,具体拆成多小的迭代器,就看业务需要了。
然后这每个小迭代器,可以交由不同的CPU进行并行计算,计算完毕后再合并。从而完成迭代器拆分,多CPU并行计算的迭代功能。
不过Spliterator只是支持并行处理,但并不提供并行处理。这个是啥 意思呢?就是说它可以拆分,拆分后具体咋处理,是同步执行还是异步并行执行,Spliaterator就根本不关心,那是开发者自己的事情。
fork/join模式
利用Spliterator实现并行迭代的功能,一般都采用fork/join框架模式。
这里又出来一个fork/join模式,这是一种开发模式,应该也是一种设计模式吧。这个模式的思想就是对Spliterator进行递归处理,每次递归都判断一下迭代器是否足够小了,如果不够小就继续拆分,也就是就行fork,fork就是一个分叉,把大的拆成小的。
如果够小了就开始执行,执行结果返回然后进行合并,也就是 join 。
通过这个思路,将Splitrator递归拆成多个足够小的迭代器,然后交给多个CPU并行处理。
ForkJoinPool
针对这个思想,Java提供了 ForkJoinPool,利用这个就可以实现 fork/join模式。
这个类是 ExecutorService 的实现类,ExecutorService 一般配合Callable实现有返回值的多线程。不过Callable 是阻塞的,并不能达到真正的多CPU并行,也就是说多个Callable其实是一个执行完了再执行另一个。
而ForkJoinPool则可以实现真正的并行执行。
因此利用ForkJoinPool+Spliterator ,可彻底的释放CPU的能量。
这个Spliterator确实是新版Java提供的一个并行计算的利器。
自我点评
这个问题前两个其实都不太好讲出什么出彩的东西,唯独这个Spliterator确实强大,这个值得说一说。
再给说一个技巧,在真正面试的时候,可能面试官问的不是这个问题,人家可能只是问问ListIterator的特性。这个时候面试者一定不要只说ListIterator的性质。
有经验的面试者 一定会把话题转到Spliterator这个迭代器上,具体如何转话题,就看个人发挥了。
下期再见
好的,本期就到这里,我们下次再见。