相信 “迭代” 对于Java程序员来说并不陌生(当然,其他语言的程序员也是如此),在处理数据时,不可避免地会存在对数据的大量遍历操作。对于我自己而言,学习使用Java语言两年时间,对于“迭代”的概念还停留在 for:each
,for:i
的遍历阶段。今天用到了JDK 提供的迭代接口进行 Java 集合的迭代,便决定作以笔记,留作以后学习。
普通 Java 集合迭代(遍历)
迭代可以简单理解为遍历,在没有 JDK 并未提供迭代器时,我们对于数据的遍历处理如下:
- 对于数组的遍历处理:
Bean[] beans = new Bean[5];
for (int i = 0; i < beans.length; i++) {
beans[i] = new Bean();
// todo something
}
- 对 ArrayList 的遍历处理:
ArrayList beanArrayList = new ArrayList();
for (int i = 0; i < beanArrayList.size(); i++) {
beanArrayList.add(new Bean());
// todo something
}
可以看出,如果我们想对一个空的 Java 集合添加数据,那我们就必须知道该集合内部的数据结构(即,以数组和 ArrayList 为例,添加时的操作应该是beans[i] = new Bean();
还是beanArrayList.add(new Bean());
),这样就导致了访问逻辑与集合的结构本身紧密耦合(即,每一种不同的数据集合对应了不同的便利方法),这会使得代码无法复用。
而 Iterator
可以轻松的解决上述问题.
java.util.Iterator
看一下官方未出的解释:
public interface Iterator
An iterator over a collection.Iterator
takes the place ofEnumeration
in the Java Collections Framework. Iterators differ from enumerations in two ways:
- Iterators allow the caller to remove elements from the underlying collection during the iteration with well-defined semantics.
- Method names have been improved.
This interface is a member of the Java Collections Framework
就是说,Iterator
是一个对 collection 集合进行迭代的迭代器(接口)。Iterator
迭代器取代了 Java Collections Framework 中的 Enumeration
。该接口是 Java Collections Framework 的成员。迭代器与枚举有两点不同:
- 迭代器允许调用者利用定义良好的语义在迭代期间从迭代器所指向的 collection 移除元素。
- 方法名称得到了改进。
.
这也就意味着,Iterator
使用相同的访问逻辑完成集合的遍历,使得我们在访问集合元素时,无需关心不同的集合内部结构。从而降低访问逻辑与集合本身的耦合度。
Iterator
接口源代码如下:
package java.util;
import java.util.function.Consumer;
public interface Iterator {
// 返回迭代是否有更多的元素。
boolean hasNext();
// 返回迭代器刚越过的元素的引用
E next();
// 从底层集合中移除此迭代器返回的最后一个元素(可选操作)
default void remove() {
throw new UnsupportedOperationException("remove");
}
// 对每个剩余的元素执行给定的操作,直到处理完所有元素或操作抛出异常
default void forEachRemaining(Consumer super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
如何使用 Iterator
在使用中,我们既可以借助hasNext()
及next()
方法,对已知集合结构的集合对象完成简单的迭代(类似于之前的方案),就像这样:
Iterator beanIterator = beanArrayList.iterator();
while (beanIterator.hasNext()) {
Bean bean = beanIterator.next();
// todo something
}
更新于2017.12.03
仅仅这样不是与之前的方案没什么区别了吗?当然,它能做的还可以更多。做到真正不去关心集合内部结构的迭代手段,下述代码是对一个集合对象的迭代:
public static boolean isExist(Collection beans, Bean bean) {
Iterator iterator = beans.iterator();
System.out.println(beans.getClass().getSimpleName() + ":");
while (iterator.hasNext()) {
if (iterator.next().equals(bean)) {
System.out.println("集合中已存在 Bean[" + bean + "]");
return true;
}
}
return false;
}
Test:
public static final void main(String[] args) {
Bean bean0 = new Bean().setId("01");
Bean bean1 = new Bean().setId("02");
ArrayList beanArrayList = new ArrayList<>();
Queue beanQueue = new LinkedBlockingQueue<>();
HashMap map = new HashMap<>();
beanArrayList.add(bean0);
beanArrayList.add(bean1);
map.put(bean0, bean0);
map.put(bean1, bean1);
beanQueue.add(bean0);
beanQueue.add(bean1);
isExist(map.keySet(), bean0);
isExist(beanArrayList, bean1);
isExist(beanQueue, bean1);
}
输出结果:
KeySet:
集合中已存在 Bean[Bean{id='01', password='null'}]
ArrayList:
集合中已存在 Bean[Bean{id='02', password='null'}]
LinkedBlockingQueue:
集合中已存在 Bean[Bean{id='02', password='null'}]
总结
所有Collection框架中的j几乎所有的集合类(或接口)(如ArrayList、Set、Queue等)都实现了(接口也声明了iterator()
方法)自己的内部的迭代器,但无疑都是Iterator
的实现。
不过据我现在所了解到的,数组由于其本身的实现方案与 "编译处理和
JVM 的native()
方法有关,似乎不能直接获取到其本身的迭代器。如果有哪位朋友知道相关方法,请评论告知,不胜感谢。
这是第一次尝试写学习笔记,希望以后可以坚持下去,事无巨细地,从点滴累积自己的财富。