1.迭代器概述
在 Java 中,迭代器模式是一种常用的设计模式,用于遍历集合中的元素。迭代器是一种对象
,在不了解集合底层数据结构的情况下可以按照按照顺序访问集合中的元素。在Java中,提供了Iterator接口作为迭代器的基础接口。
Java中的迭代器接口实现:
public interface Iterator<E> {
/**
* 判断当前指针所指位置是否含有元素
*/
boolean hasNext();
/**
* 1)返回当前指针所指位置的元素
* 2)指针下移一位
*/
E next();
/**
* 移除指针所指的元素(迭代器返回的最后一个元素)。
* 需要注意的是,此方法仅能在调用next()方法后调用一次
*/
default void remove() {
throw new UnsupportedOperationException("remove");
}
/**
* forEachRemaining()方法可以实现逐个取出集合中的元素进行操作,操作并不会影响集合中本身的元素
*/
default void forEachRemaining(Consumer<? super E> action) {
Objects.requireNonNull(action);
while (hasNext())
action.accept(next());
}
}
案列1:
Collection<Integer> coll = new ArrayList<>();
coll.add(1);
coll.add(2);
coll.add(3);
coll.add(4);
Iterator<Integer> iterator = coll.iterator();
iterator.forEachRemaining(
num -> {
num = num + 8;
System.out.println("=》" + num);
}
);
System.out.println(coll);
2.Iterator源码分析
private class Itr implements Iterator<E> {
int cursor; // cursor记录下一个元素的索引
int lastRet = -1; // lastRet记录最后一位元素的索引,若未找到则返回-1
int expectedModCount = modCount; // 记录
Itr() {}
// 判断当前指针所指位置是否有元素
public boolean hasNext() {
return cursor != size;
}
// 获取当前指针所指向的位置的元素,并且将course指针向后移动一位
@SuppressWarnings("unchecked")
public E next() {
// 检查modCount值是否被修改,若被修改则抛ConcurrentModificationException并发修改异常
checkForComodification();
int i = cursor;
if (i >= size)
// 当指针移动到集合最大长度时,则抛NoSuchElementException异常
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
// course指针向后移动一位
cursor = i + 1;
// 取出元素
return (E) elementData[lastRet = i];
}
// 移除集合中的元素
public void remove() {
if (lastRet < 0)
throw new IllegalStateException();
checkForComodification();
try {
ArrayList.this.remove(lastRet);
cursor = lastRet;
lastRet = -1;
expectedModCount = modCount;
} catch (IndexOutOfBoundsException ex) {
throw new ConcurrentModificationException();
}
}
// 将集合中的元素逐个取出做指定操作,指定操作在accpet()方法中实现
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
// requireNonNull(Object obj)判断当前当前对象是否为null,若为null则抛空指针异常,不为null则返回
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
// 将List对象中的集合赋值给新的变量数组elementData[]
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
// 遍历新数组elementData[]
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
cursor = i;
lastRet = i - 1;
checkForComodification();
}
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
3. 注意
- 在使用Iterator时,不能再循环的过程中使用List接口中的原生API,因为在使用List中的API时都会对ModeCount值进行修改,导致checkForComodification()方法校验不成功,抛并发异常;
- 在Iterator遍历的过程中可以使用Iterator中的方法对原集合中的数据进行操作。例如:
// 修改集合中的操作,可以使用Iterator中的定义方法
Iterator<Integer> iterator2 = list.iterator();
while (iterator.hasNext()) {
Integer next = iterator2.next();
iterator2.remove();
}
4.迭代器的使用场景
遍历集合:
// 遍历单列集合
Collection<String> coll = new ArrayList<>();
coll.add("1");
coll.add("2");
coll.add("3");
coll.add("4");
Iterator<String> iterator = coll.iterator();
while (iterator.hasNext()) {
String next = iterator.next();
}
// 遍历双列集合
Map<String,Integer> map = new HashMap<>();
map.put("1",1);
map.put("2",2);
map.put("3",3);
map.put("4",4);
Iterator<String> iteratorStr = map.keySet().iterator();
while (iteratorStr.hasNext()) {
String next = iteratorStr.next();
}