Foreach 那点事
foreach 背后
平常我们循环一个 List 大概有下面这三种方式:
传统 for 循环
for (int i = 0; i < list.size(); i++) {
}
用迭代器进行迭代遍历
Iterator itr = list.iterator();
while (itr.hasNext()) {
itr.next();
}
增强 for 循环,也就是 foreach
for (String str : list) {
}
如果你用 idea 进行开发的话,用迭代器进行遍历的时候,它会提醒你可以换成 foreach 循环,这说明这两者是一样的。事实上 foreach 循环只是迭代器循环的一种简便形式而已。
在 jdk 源码中,我们可以看到有 Iterable 这么一个接口,顾名思义,就是可迭代的意思,再看这个接口的具体内容:
/**
* Implementing this interface allows an object to be the target of
* the "foreach" statement.
*
* @param <T> the type of elements returned by the iterator
*
* @since 1.5
*/
public interface Iterable<T> {
Iterator<T> iterator();
}
注意注释中内容,实现这个接口,可以让一个类能够使用 foreach 形式进行迭代。然后再看看唯一的方法返回值 Iterator,顾名思义就是迭代器,再看看迭代器源码:
public interface Iterator<E> {
// 是否有下一个元素
boolean hasNext();
// 获取下一个元素
E next();
// 删除当前元素
void remove();
}
Iterator 迭代器只是一个接口,里面的相关操作还须要用户自己实现。
实现自己的可迭代的类
有了上面的基础,我们就可以实现一个最简单的 List
// 首先实现 Iterable 接口
public class IteratorDemo<T> implements Iterable<T> {
private Object[] table;
private int size;
public IteratorDemo(int capacity) {
table = new Object[capacity];
}
// 实现获取迭代器的方法
@Override
public Iterator<T> iterator() {
return new Itr();
}
public boolean add(T t) {
if (size == table.length) {
return false;
}
table[size++] = t;
return true;
}
public int size() {
return size;
}
public boolean isEmpty() {
return size == 0;
}
// 定义迭代器实现类
class Itr implements Iterator<T> {
private int cursor;
@Override
public boolean hasNext() {
return cursor + 1 <= size;
}
@Override
@SuppressWarnings("unchecked")
public T next() {
return (T) table[cursor++];
}
@Override
public void remove() {
}
}
public static void main(String[] args) {
IteratorDemo<String> demo = new IteratorDemo<>(2);
demo.add("hello");
demo.add("world");
for (String s : demo) {
System.out.println(s);
}
}
}
控制台
hello
world
Process finished with exit code 0
作用
知道 Iterator 相关的内容,再去看 ArrayList、HashMap 等源码会轻松许多~