foreach的实现机制
目前工作稳定下来,可以在摸鱼时间写点东西了。现在先来点简单的,foreach实现机制。或许后面会有大的💊来了。
forEach源码:
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
需要使用forEach方法的类必须实现iterable接口,它调用的foreach语法糖会调用以下方法:
1)iterator()
这是iterable接口中的一个方法,返回一个实现了iterator接口的类。尽管foreach语法糖中没有调用该方法,但会默认调用,如图1所示。
foreach语法糖依靠hasNext和next方法从调用forEach方法的对象中取出元素,并执行给定的方法。这是常规迭代器模式操作方式,不做赘述。图2证明forEach确实调用hasNext和next方法:
最后附上实际项目中对foreach语法糖的应用。在某个项目中,使用了开源框架MetaModel进行数据库的访问。MetaModel框架是一个用于数据访问的框架,它试图整合所有关系型,非关系型,文档数据库等所有形式的数据库的访问方式,向外提供统一的访问接口。
下面是调用foreach的项目源码,声明一点,不是我写的,也不是我朋友写的,真的和我没关系。
ds.forEach((row) -> {
Map<String, Object> r = new LinkedHashMap();
for(int i = 0; i < columns.size(); ++i) {
String name = ((SelectItem)columns.get(i)).getSuperQueryAlias();
if (StringUtils.isNotBlank(name) && name.contains(".")) {
name = this.getColumnNameFromSelectItem((SelectItem)columns.get(i));
}
if (name.startsWith("\"") || name.startsWith("`")) {
name = name.substring(1);
}
if (name.endsWith("\"") || name.endsWith("`")) {
name = name.substring(0, name.length() - 1);
}
r.put(name, dataConvert(row.getValue(i)));
}
rows.add(r);
});
代码逻辑并不重要,关键是ds对象。ds对象是MetaModel框架中,JdbcDataSet类的对象。它有一个抽象父类,名字为AbstractDataSet,它实现了Iterable接口。当我们调用ds.forEach()时,它将首先调用AbstractDataSet的Iterator(),如图5所示。
DataSetIterator有关于数据集的处理逻辑,具体就不解析了。这里想要告诉读者的是,当对迭代过程有特殊要求,或者想要为专门的类设置专门的迭代器时,可以考虑创建一个新的迭代器类。