看了CS61B这部分的网课两遍,感觉要好好记录下来,不然接下来还是容易忘。
首先,究竟是什么原因让我们揪出来了Iterator这个东西呢?我们先看一段代码:
//assume we have an ArrayList called AList, which contains String type items //we want to create a method to print out all the items in the list public void printAList(ArrayListALits) { for(String x : AList) { System.out.println(x); } }
这个方法可以打印出AList中的每个元素,运行结果如图所示:
我们不调用java.util.ArrayList, 而是自己创建一个ArrayList,正好可以借用之前的AList(CS61B之前的课上跟着做的)来用一用这个方法:
public class AList- { private item[] items; private int size; public AList() { items = (item[]) new Object[100]; //create a array which length is 100 (0-99) size = 0; } private void resize(int capacity){ item[] a = (item[]) new Object[capacity]; System.arraycopy(items, 0, a, 0, size); items = a; } public void addLast(item x) { if(size == items.length){ resize(size * 2); //uses multiply to set size, to save time consuming } items[size] = x; size += 1; } public item getLast() { return items[size - 1]; } public item get(int i) { return items[i]; } public int size() { return size; } public item removeLast() { item x = getLast(); items[size - 1] = null; //release the spaceS size -= 1; return x; } }
我们在main函数中使用了与之前对ArrayList相同的操作:
public static void main(String[] args) {
AList Alist = new AList<>();
Alist.addLast("Apple");
Alist.addLast("Pear");
Alist.addLast("Pineapple");
for(String x : Alist) {
System.out.println(x);
}
}
但是结果并不尽如人意,编译器报错:
也就是说,这个语句成型的条件是冒号后面需要一个java.lang.Iterable类型的东西或者是个数组,但是目前我们自己设计的ArrayList并不具备这个功能。从这里,我们找到了一个很有意思的东西——java.lang.Iterable。
我们来研究一下Iterableemm,代码有点多,我就把一部分注释都去掉了,主要内容其实就一点点:
package java.lang; import java.util.Iterator; import java.util.Objects; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; public interface Iterable{ Iterator iterator(); default void forEach(Consumer super T> action) { Objects.requireNonNull(action); for (T t : this) { action.accept(t); } } default Spliterator spliterator() { return Spliterators.spliteratorUnknownSize(iterator(), 0); } }
主要我们关注这一语句import java.util.Iterator;我们把目光放在iterator()上,看来还得往下扒一层皮。
还得再研究一下Iterator我们进一步挖挖Iterator.java里面的那内容吧(还是一样,为了精简篇幅,把大部分注释去掉了):
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()); } }
我们看到在interface Iterator中,我们有两个interface method和两个default method,其中interface method中一个是hasNext(),一个是next()。我们可以用运用目前所知道的方法,创建出来一个“低端”的printAList method吗?
如何理解Iterator是关键我们如何思考这个问题呢,其实也和物理、化学实验一样,我们用控制变量的角度看看:
| 调用了java.util.ArrayList的AList | 自创的AList |
|---|---|
| interface: 拥有Iterator | interface:无 |
| Iterator中的method:1. next();2. hasNext() | 还是无。。。 |
也就是说,我们自己的ArrayList缺少了一些东西导致了目前无法实现for(String x : Alist) 语句
那么现在,我先在调用了java.util.ArrayList的ArrayList中通过Iterator实现for(String x : Alist)所实现的功能——遍历打印,之后再向自己所创建的ArrayList中添加响应的函数,使其也可以使用相同的方法,最终实现for(String x : Alist)
我们首先用现成的条件来实现Iterator的使用。因为我们已经知道了java.util.ArrayList中有了Iterable,而Iterable用这种方式引入了iterator:Iterator
- hasNext()函数:
Returns true if the iteration has more elements. (In other words, returns true if next would return an element rather than throwing an exception.)
Returns: true if the iteration has more elements
也就是说,只要后面还有东西,就返回个true - Next()函数:
Returns the next element in the iteration.
Returns: the next element in the iteration
Throws: NoSuchElementException – if the iteration has no more elements
也就是有数就返回这个数,没数就去执行NoSuchElementException。
所以我们可以用hasNext()判断是否列表后面还有数,用Next()进行打印。
哦,对了,我们还要简单的创建一个数组:
import java.util.Iterator;
import java.util.ArrayList;
public class ArrayDemo {
public static void main(String[] args) {
ArrayList aList = new ArrayList<>();
aList.add("Apple");
aList.add("Pear");
aList.add("Pineapple");
Iterator seer = aList.iterator();
while(seer.hasNext()){
System.out.println(seer.next());
}
}
}
运行结果如图所示:
回到我们自己创建的ArrayList中,我们现在还什么都没有呢!
为了可以使用Iterator,按照之前分析的顺序,我们需要implements Iterable,之后我们要创建一个iterator method,并且要返回一个Iterator类型的迭代器:
//implements Iterable public class AList- implements Iterable
- {
//create iterator method
public Iterator- iterator() {
return new AListIterator();
}
OK, 那既然创建的这个AListIterator是Iterator类的,我们必须让AListIterator中包含Iterator中该有的东西(hasNext() & next()),所以我们要构建一个class,将其命名为AListIterator然后添加一个构建器(用于调用)两个method:
public class AListIterator implements Iterator- { private int pointer; public AListIterator() { pointer = 0; } public boolean hasNext() { return pointer < size; } public item next() { item returnAlist = items[pointer]; pointer += 1; return returnAlist; } }
pointer作为一个指针,用于指向列表中的内容,因为hasNext()和next()都需要进行判断,别忘了next()中要让pointer自增1
当我们实现了这些功能后,现在可以大摇大摆的在我们自己创建的ArrayList中使用Iterator了!
public static void main(String[] args) {
AList alist = new AList<>();
alist.addLast("Apple");
alist.addLast("Pear");
alist.addLast("Pineapple");
AList.AListIterator aListIterator = alist.new AListIterator();
while(aListIterator.hasNext()) {
System.out.println(aListIterator.next());
}
}
输出结果:
我们来看看我们的终极目标:在自己制作的ArrayList中是否能使用for(String x : xxx)这样的语句了呢?
for(String x : alist) {
System.out.println(x);
}
输出结果:
OK,最后的最后,我们成功了!



