和 lvgo 一起学设计模式(十八)行为型之迭代器模式
Posted 星尘的一个朋友
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了和 lvgo 一起学设计模式(十八)行为型之迭代器模式相关的知识,希望对你有一定的参考价值。
不一样的原创沉淀内容在等你关注!
迭代器模式
❝提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
❞
在看迭代器模式之前,我觉得应该来研究一段代码开开胃先。
Java 中的 List 集合遍历
public class Appetizer {
public static void main(String[] args) {
ArrayList<String> strings = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
strings.add("第" + i + "个元素");
}
Iterator<String> iterator = strings.iterator();
while(iterator.hasNext()) {
iterator.next();
}
}
}
这段代码很简单,我们在日常开发中可能也是经常使用到。有的人可能会说了,啊不对,我用的都是
for(int i = 0; i < strings.size(); i++)
还有的朋友说了,我直接用增强for
循环啊
for(String s : Strings)
class
文件来一探究竟吧。
这里使用三种不同的写法来遍历一个 list
「java 源码文件」
// 1. 使用迭代器遍历
Iterator<String> iterator = strings.iterator();
while(iterator.hasNext())
iterator.next()
// 2. jdk 8 提供的 lambda 写法
strings.forEach(System.out::println);
// 3. 增强 for 循环写法
for (String string : strings) {
System.out.println(string);
}
// 4. 下标遍历
for (int i = 0; i < strings.size(); i++) {
System.out.println(strings.get(i));
}
「class 反编译的 java 文件内容」
// 1. 使用迭代器遍历
Iterator<String> iterator = strings.iterator();
while(iterator.hasNext()) {
iterator.next();
}
// 2. jdk 8 提供的 lambda 写法
var10001 = System.out;
strings.forEach(var10001::println);
Iterator var3 = strings.iterator();
// 3. 增强 for 循环写法
while(var3.hasNext()) {
String string = (String)var3.next();
System.out.println(string);
}
// 4. 下标遍历
for(int i = 0; i < strings.size(); ++i) {
System.out.println((String)strings.get(i));
}
第一种和第三种可以算为同一种,所以就只剩下三种迭代方式
// 1. 增强 for 循环(迭代器)
for(String s : Strings)
// 2. JDK8 的 forEach 方法
Strings.forEach()
// 3. 下标遍历
for(int i = 0; i < strings.size(); i++)
接下来我们用数据来看一下这几种方式的表现情况
「第一次」
测试方法:iterator
测试数据量:1000000
花费时长(ms):21
-----------------------------
测试方法:forEach
测试数据量:1000000
花费时长(ms):132
-----------------------------
测试方法:增强 for 循环
测试数据量:1000000
花费时长(ms):18
-----------------------------
测试方法:下标遍历
测试数据量:1000000
花费时长(ms):1
-----------------------------
「第二次」
测试方法:iterator
测试数据量:1000000
花费时长(ms):17
-----------------------------
测试方法:forEach
测试数据量:1000000
花费时长(ms):123
-----------------------------
测试方法:增强 for 循环
测试数据量:1000000
花费时长(ms):12
-----------------------------
测试方法:下标遍历
测试数据量:1000000
花费时长(ms):3
-----------------------------
「第三次」
测试方法:iterator
测试数据量:1000000
花费时长(ms):18
-----------------------------
测试方法:forEach
测试数据量:1000000
花费时长(ms):119
-----------------------------
测试方法:增强 for 循环
测试数据量:1000000
花费时长(ms):14
-----------------------------
测试方法:下标遍历
测试数据量:1000000
花费时长(ms):2
-----------------------------
为了更直观的展示,我整理了一张统计图
通过数据也证实了 「迭代器」 和 「增强 for 循环」的写法效果相同。
List 集合到底该如何遍历
ArrayList
增加了
public interface RandomAccess {
}
标记。标记其为随机访问集合。
List
集合的遍历,我们就讨论这么多,更主要的是我们要讨论一下上面提到的一个东西,
「“迭代器”」
❝文末关注回复“源码”获取本文测试使用代码及图表数据
❞
迭代器
❝图片来源:https://refactoringguru.cn/design-patterns/iterator
❞
DFS
方式遍历,写好了一个算法在集合类中,后面发现有需要
BFS
方式遍历这个集合,以目前这种方式,就只能去修改集合类,再加一个方法。如果哪天发现这两个都不合适,又要加一个呢,慢慢的,集合本身的存取目的开始变得不明确,这其实是因为违反了
单一职责
原则。
❝提供一种方法来顺序访问聚合对象中的一系列数据,而不暴露聚合对象的内部表示。
❞
JDK
中是怎么样用这个迭代器模式来设计集合遍历程序的。go!