迭代(iterate):简单来说, 它就是一个循环。 集合框架中的Iterator接口定义了迭代器的功能, 迭代器的用途是遍历集合(容器) 中的所有元素。
1. 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());
}
}
import java.util.ArrayList;
import java.util.Iterator;
class Test {
private ArrayList<String> names;
Test() {
names = new ArrayList<String>();
names.add("zhang");
names.add("wang");
names.add("li");
names.add("zhao");
}
public void print() {
// 获取迭代器
Iterator<String> it = names.iterator();
// 输出集合中的第一个元素
System.out.println(it.next());
}
public void show() {
// 输出所有元素
Iterator<String> it = names.iterator();
while(it.hasNext()) {
System.out.println(it.next());
}
}
public void remove() {
Iterator<String> it = names.iterator();
while(it.hasNext()) {
if(it.next().equals("zhang"))
it.remove();
}
System.out.println(names);
}
}
public class App {
public static void main(String[] args) {
new Test().print();
System.out.println("-----------");
new Test().show();
System.out.println("-----------");
new Test().remove();
}
}
注意:Java 迭代器是一种单向遍历机制,即只能从前往后遍历集合中的元素,不能往回遍历
。同时,在使用迭代器遍历集合时,不能直接修改集合中的元素,而是需要使用迭代器的 remove() 方法来删除当前元素。
2. 迭代器与for…each循序
Java 5 引入了 for...each
循环, 它天生就是为迭代器而设计的, 只要集合类实现了Iterable接口, 就可以使用 for...each" 循环
, 而Collection这一系的集合类都实现了Iterable接口, 所以都可以应用for...each
循环。这个东西呢在C++中叫区间for循环
,当然,在Java中也可以这样称谓它。
public class App {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("111");
list.add("222");
list.add("333");
list.add("444");
// for...each循环
for(String str: list) {
System.out.println(str);
}
}
}
当然了,如果我们自己写的类实现了Iterable接口, 那么它也可以应用“for…each”循环。
public interface Iterable<T> {
Iterator<T> iterator();
default void forEach(Consumer<? super T> action) {
Objects.requireNonNull(action);
for (T t : this) {
action.accept(t);
}
}
default Spliterator<T> spliterator() {
return Spliterators.spliteratorUnknownSize(iterator(), 0);
}
}
class MyList implements Iterable<Integer> {
@Override
public Iterator<Integer> iterator() {
return new Iterator<Integer>() {
private int[] arr = new int[] { 2, 4 , 5, 232, 121 };
private int pos = 0;
@Override
public boolean hasNext() {
return pos < arr.length;
}
@Override
public Integer next() {
return arr[pos++];
}
};
}
}
public class App {
public static void main(String[] args) {
MyList list = new MyList();
for(Integer num: list) {
System.out.print(num + " ");
}
}
}
3. forEach()方法
Java8为Iterable接口新增了forEach()
方法默认方法。可以在实现Iterable接口的对象上调用forEach()方法。
public class App {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<String>();
list.add("111");
list.add("222");
list.add("333");
list.add("444");
list.forEach(elem -> System.out.print(elem + " ")); // 使用lambda表达式传参
System.out.println("");
list.forEach(System.out::println); // 使用方法引用传参
}
}
4. ListIterator接口
实现Iterator接口的迭代器只能朝着一个方向遍历集合中的元素, 在大多数情况下, 这已经能满足我们的需求了, 但在有些情况下, 我们也希望能够按任一方向遍历集合, 并可以在迭代期间修改集合
, 为此, 集合框架中给出了ListIterator
接口。
public class App {
public static void main(String[] args) {
List<Integer> list = new ArrayList<Integer>();
list.addAll(Arrays.asList(1, 2, 3, 4, 5));
ListIterator<Integer> lsIt = list.listIterator();
System.out.println("正向遍历:> ");
while(lsIt.hasNext()) {
System.out.print(lsIt.next() + " ");
}
System.out.println(lsIt.nextIndex()); // 5
System.out.println("\n------------------");
System.out.println("反向遍历:> ");
while(lsIt.hasPrevious()) {
System.out.print(lsIt.previous() + " ");
}
System.out.println("\n------------------");
/*
* nextIndex:> 返回后续调用next()方法所返回的元素的索引位置; 如果迭代器在列表结尾, 则返回列表的大小;
* previousIndex:> 返回... previous() ...; 如果迭代器在列表开始, 则返回-1;
* */
System.out.println("迭代器索引位置:> ");
System.out.println(lsIt.nextIndex()); // 0
System.out.println(lsIt.previousIndex()); // -1
while(lsIt.hasNext()) {
lsIt.next();
}
System.out.println("索引位置:> ");
System.out.println(lsIt.nextIndex()); // 5
}
}