迭代的 .hasNext() 的使用;和 .next();Java 中的方法



两天来,我对.hasNext()非常困惑next()迭代接口的方法,尤其是在while循环中。让我举一个例子:

import java.util.*;  // imported whole java.util package.
class Main {
public static void main(String[] args) {
ArrayList<String> cars = new ArrayList<String>();  // created ArrayList which name is cars.
cars.add("Volvo");
cars.add("Mercedes"); 
cars.add("BMW");

Iterator<String> x = cars.iterator();
while(x.hasNext()) {
System.out.print(x.next() + " ");  // It prints Volvo Mercedes BMW
}
}
}

我知道.hasNext()是布尔值,如果迭代有元素,则返回true。.next()方法返回下一个元素。在第一个元素Volvo之后,它在(x.hasNext())时返回,并再次进入循环内部,但这个循环的计数器在哪里?我的意思是,在印完沃尔沃之后,它怎么能进入下一个元素呢?它返回所有元素,如果没有.hasNext()返回false,代码继续到下一行。这是一个简单的答案,也是正确的,但我想清楚地理解它。

实际上迭代器()方法为数组列表中的所有元素创建一个迭代器。现在在您的代码中,while循环x.hasNext()的条件检查列表是否包含元素,如果是,则返回true,否则返回false。

现在,x.next()指向ArrayList中的First Element(例如LinkedLists),并存储该Object(在您的情况下为Volvo)。当您调用此方法时,它基本上会为您提供列表中该对象的引用,并且迭代程序会移动到列表中的下一个元素。当调用next()方法时,迭代器(在您的情况下为x)返回对象,然后移动到下一个元素(在您情况下为Mercedes)。

现在,当您再次调用next()方法时,您会发现Mercedes已返回。要想知道它是如何工作的,请键入System.out.println(x.next())三次,而不是while循环,您将知道它会移动到下一个位置。如果您第四次键入System.out.println(x.next()),它将给出异常,因为您的列表中再也没有元素了线程中的异常";主";java.util.NoSuchElementException这是异常。

这就是为什么在检查元素是否存在时使用hasNext()方法的原因。您可以将其与linkedlist(如果您知道,则为数据结构)的打印进行比较,在这里,我们将一个对象指向头节点,打印它并移动到下一个节点。这里的情况相同,它返回当前元素(对象)并移动到下一个元素(对象(object))。

while是java语言:继续这样做,直到事情发生变化。

这有点像这个常见的家庭任务:

如何洗碗

  • 检查柜台右侧是否还有脏盘子
  • 如果有的话,做洗碗的事:拿起最近的脏盘子,洗干净,然后把它放在柜台的左侧,然后回到这个算法的开始
  • 否则(没有脏盘子),你就完了
while (counterRightSide.hasItems()) {
Dish dirty = counterRightSide.fetch();
Dish clean = sink.clean(dirty);
counterLeftSide.stow(clean);
}

编辑:我现在意识到"厨房柜台"是一个不幸的例子,因为同音词"kitchen counter"one_answers"counter in code"。我将使用"accumulator"而不是"counter in code"来修复这种混乱。

注意这里也没有累加器,洗碗时你也不会在脑子里数。你可以先盘点一下你有多少脏盘子(比如说,15个盘子),然后写一个协议,在判定你完成了这项工作之前,你准确地抓了一个脏盘子15次,但你肯定意识到这只是一种方法,另一种是。。。每次洗完一个脏盘子后,检查是否还有脏盘子。以上代码就是这样工作的。

请注意,从厨房柜台右侧"取出"物品的操作将更改该厨房柜台的属性。它现在少了一个项目。

迭代器也是如此:在迭代器上调用.next()会以某种形式改变它。毕竟,如果您调用next两次,这些调用的结果会有所不同。与连续多次调用someArrayList.get(5)形成对比;这根本不会改变数组列表,因此每次都会得到相同的东西。next()并非如此。

那么这是怎么回事呢?谁数这些东西

这就是抽象的巧妙之处!"集合"可以做一些事情,例如"它必须能够报告它包含的项目数",以及"它必须能为您挂上一个对象,该对象可用于循环遍历它包含的每个项目"。

迭代器就是这样:一个可以做到这一点的对象。

那么它是如何工作的呢谁知道!没关系!只要你能做到这些,你就可以成为一个集合,你可以随心所欲地执行任务。

好吧,但是像ArrayList这样的普通集合是如何做到这一点的呢

当然还有柜台。以下是实现:

public Iterator<T> iterator() {
return new Iterator<T>() {
int counter = 0; // here it is!

public boolean hasNext() {
return counter < size();
}
public int next() {
return get(counter++);
}
};
}

你得到这个对象并在代码中引用它(你的x变量),而这个对象有一个带计数器的字段。你看不到它;它是私有的,实际上不是Iterator类型(Iterator是一个接口;您得到的是它的某个未知子类型,它包含计数器变量)。这是假设您通过调用arraylist上的.iterator()来获得迭代器。如果你在其他东西上调用它,可能有计数器,也可能没有计数器——只要迭代器工作,它如何工作并不重要,这就是接口的美妙之处。

while循环检查条件,当条件为true时,执行循环主体并迭代自身,

while(condition){
//do something.
}

hasNext()是来自Iterator接口的一个方法,如果";迭代";有更多元素,如果没有更多元素,它将返回fals,并且将不再进入while循环的主体:

while(x.hasNext){
//do something.
}

next()方法是Iterator接口中的一个方法,它返回迭代的下一个元素。

while(x.hasNext){
x.next();
}

我的意思是,在打印沃尔沃之后,它如何进入下一个元素?它返回所有元素,如果不存在,则返回.hasNext();返回false代码继续到下一行是简单的答案和正确的,但我想弄清楚。

int cursor;       // index of next element to return
//...
public boolean hasNext() {
return cursor != size;
}
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];
}
//...

上面给出了ArrayList#hasNextArrayList#next是如何实现的。代码直截了当,易于理解。你可以使用反编译器或在这里检查完整的代码。

最新更新