文章目录
1. 概念
Iterator对象也被称为迭代器,它主要用于遍历Collection集合中的的元素。
迭代器模式:给迭代器 模式的定义为:提供一种方法访问个容(container) (container) (container) 对象中各个元 素,而又不需暴露该对象的内部细节。
2. 常用方法
java.util.Iterator接口中常用的方法:
boolean hasNext():判断集合中是否还有没有下一个元素,有则返回true,否则返回falseE next():返回迭代的下一个元素
Iterator是一个接口,如果要使用它需使用Iterator接口的实现类对象。Collection继承了Iterator接口,因此,Colleantion接口的实现类对象可以使用iterator()方法用于返回迭代器的实现类对象
Iterator<E> iterator():返回在此collection的元素上进行迭代的迭代器
使用步骤:
- 使用集合中的方法
iterator()获取迭代器的实现类对象,使用Iterator接口接收 - 使用Iterator接口中的方法
hasNext()判断还有没有下一个元素 - 使用Iterator接口中的方法
next()取出集合中的下一个元素
public class IteratorDemo {
@Test
public void testList() {
Collection<String> col = new ArrayList<>();
List<String> list = new ArrayList<>();
Collections.addAll(list, "Forlogen", "Kobe", "James");
col.addAll(list);
System.out.println(Arrays.toString(col.toArray()));
System.out.println("-----------");
//Iterator<E>接口也是泛型的,迭代器的泛型跟着集合走
Iterator<String> iter = col.iterator();
while (iter.hasNext()) {
System.out.println(iter.next()); // Forlogen kobe
}
System.out.println("-----------");
// for-each遍历
for (String s : col) {
System.out.println(s);
}
System.out.println("-----------");
// Lambda表达式遍历
col.forEach((t) -> System.out.println(t));
System.out.println("-----------");
}
/*
[Forlogen, Kobe, James]
-----------
Forlogen
Kobe
James
-----------
Forlogen
Kobe
James
-----------
Forlogen
Kobe
James
-----------
*/
@Test
public void testSet(){
Set<String> set = new HashSet<>();
Collections.addAll(set,"Forlogen", "Kobe", "James","James");
Iterator<String> iterator = set.iterator();
while (iterator.hasNext()){
System.out.println(iterator.next());
}
}
/*
Forlogen
Kobe
James
*/
}
3. Iterator的源码
public interface Iterator<E> {
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()两个方法,任何实现这个接口的类都要重写这两个方法。下面我们看一下ArrayList中对于这两个方法是如何实现的:
private class Itr implements Iterator<E> {
int cursor; // index of next element to return
int lastRet = -1; // index of last element returned; -1 if no such
int expectedModCount = modCount;
Itr() {}
public boolean hasNext() {
return cursor != size;
}
@SuppressWarnings("unchecked")
public E next() {
checkForComodification();
int i = cursor;
if (i >= size)
throw new NoSuchElementException();
Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length)
throw new ConcurrentModificationException();
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();
}
}
@Override
@SuppressWarnings("unchecked")
public void forEachRemaining(Consumer<? super E> consumer) {
Objects.requireNonNull(consumer);
final int size = ArrayList.this.size;
int i = cursor;
if (i >= size) {
return;
}
final Object[] elementData = ArrayList.this.elementData;
if (i >= elementData.length) {
throw new ConcurrentModificationException();
}
while (i != size && modCount == expectedModCount) {
consumer.accept((E) elementData[i++]);
}
// update once at end of iteration to reduce heap write traffic
cursor = i;
lastRet = i - 1;
checkForComodification();
}
// 判断集合的修改次数是否合法
// modCount用于记录集合被修改的次数,每当集合内部结构发生变化(add,remove,set)时,modCount+1
final void checkForComodification() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
}
}
ArrayList内部有一个Iterator接口的实现类Itr,Itr中定义了三个变量:
cursor:表示下一个元素的索引位置lastRet:表示上一个元素的索引位置expectModCount:预期被修改的次数
对于接口中方法的实现:
-
hasNext():在Iterator接口的实现类中首先设置了一个游标cursor,它用于表示当前位置是否到达了集合的最后一个元素- 如果
cursor != size,说明集合后面还有元素,返回true - 如果
cursor == size,说明已到达集合的末尾,返回false
- 如果
-
如果符合正常情况,则根据游标来获取当前位置的元素,并更新游标
4. for - each循环
借助于Iterator接口的实现。遍历操作还可以使用for-each来遍历数组和集合:
Collection<E> extends Iterable<E>:所有的打猎集合都可以使用增强for
public interface Iterable<T>:实现这个接口允许对象称为foreach语句的目标
格式:
for(集合/数组的数据里欸选哪个 变量名:集合名/数组名){
sout(变量名)
}
测试代码:
@Test
public void testForEach(){
//遍历集合
List<String> list = new ArrayList<>();
Collections.addAll(list, "Forlogen", "Kobe", "James");
for(String ele:list){
System.out.println(ele);
}
System.out.println("-----------");
// 遍历数组
String[] arr = {"James", "kobe"};
for(String ele:arr){
System.out.println(ele);
}
}
/*
Forlogen
Kobe
James
-----------
James
kobe
*/