【问题标题】:Java - ListIterator and hasNextJava - ListIterator 和 hasNext
【发布时间】:2013-06-14 01:29:10
【问题描述】:

我正在学习 Java,但 ListIterator 有问题。我有一个包含这些字符的列表:b u o n g i o r n o。我的代码返回“buongiorno”,而我希望它打印“buongiorn”,而没有尾随的“o”。由于hasNext() 函数,我期待这一点。我的代码使用递归。能解释一下原因吗?

public static String creaStringa(List<Character> lista) {
    System.out.println(lista.size());
    ListIterator<Character> it = lista.listIterator();
    return ricCrea(it);
}


public static String ricCrea(ListIterator<Character> it) {
    if(!(it.hasNext())) {
        return "";
    else
        return String.valueOf(it.next()) +ricCrea(it);
}

【问题讨论】:

    标签: java list iterator


    【解决方案1】:

    如果列表只有一个元素会更清楚,比如说“b”。 hasNext() 实际上会返回 true,next() 会读取它,然后迭代将结束。

    说明:

    如果你在任何非空列表上调用Iterator&lt;Object&gt; it= list.iterator()(即使它只有一个元素),你会因为调用hasNext() 而得到true。那是因为迭代器是在第一个元素之前初始化的:

      b u n g i o r n o
     ^
     i - iterator
    

    当您调用 next() 时,它会做两件事:

    • 它读取迭代器前面的元素,
    • 将迭代器移动到刚刚读取的元素之后,下一个元素之前。

    在您的示例中 - 它打印“b”并在“u”之前停止:

      b u n g i o r n o 
       ^
       i
    

    就在结束之前:

      b u n g i o r n o
                     ^
                     i
    

    它实际上有下一个值 - “o”。调用next() 将读取该值并在o 之后跳转。没有更多的元素。 hasNext() 会显示 false,调用 next() 会导致异常。

    技术细节:

    迭代器实现的基本思路是这样的: - 当Iterator 通过在List 上调用iterator() 创建时,其内部变量next 指向列表的第一个元素。 - hasNext() 只检查next 是否为!= null。 - next() 返回 next 并设置 next 以显示下一个元素。

    这是java.util.ArrayList迭代器(省略了一些细节):

    public Iterator<E> iterator() {
         return new Itr();
    }
    
    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;
    
         public boolean hasNext() {
             return cursor != size;
         }
    
         public E next() {
             checkForComodification();
             int i = cursor;
             Object[] elementData = ArrayList.this.elementData;
             cursor = i + 1;
             return (E) elementData[lastRet = i];
         }
    
     }
    

    【讨论】:

    • 虽然,通过这样的描绘更容易理解Iterator的工作原理;这是不正确的。以编程方式,您不能将光标指向两个元素之间,因为它只是作为索引实现的。
    • T next 指向一个元素,hasNext() 检查是否next != null, yadda, yadda,我们都知道,但这是为了更好地理解这个概念。
    【解决方案2】:

    ListIterator.hasNext() 也会为最后一个“o”字符返回true(就像所有其他字符一样)。因此,else 也会被执行。只有在获取最后一个“o”之后,hasNext() 才会返回 false(因为它现在已经超过了所有元素)。

    这里要注意的是hasNext() 只检查在next() 调用中是否还有其他东西可用于返回。它不会自行获取或跳过它。

    【讨论】:

    • 您好,谢谢您的回复。在我的意大利书中写到“下一步返回迭代器位置的值,然后将迭代器移动到下一个位置”。对吗?
    • 稍微修正一下:“next()返回迭代器当前位置的值,然后将迭代器移动到下一个位置”。
    【解决方案3】:

    迭代器开始“指向”第一个之前的项目。

    next() 使迭代器指向下一项并返回它。

    所以你实际上是在遍历整个列表。

    这是为了在迭代时启用以下语法:

    而 (it.hasNext()) { ItemClass itemValue = it.next(); // 对值做一些事情 }

    即使迭代器为空,也可以使用相同的语法。

    【讨论】:

    • 您好,谢谢您的回复。在我的意大利书中写到“下一步返回迭代器位置的值,然后将迭代器移动到下一个位置”。所以是错的?
    • 参见此处:docs.oracle.com/javase/6/docs/api/java/util/Iterator.html " Next:返回迭代中的下一个元素。"
    • 迭代器的问题在于它在概念上并不指向任何东西。只有一组有序的项目,您可以获得下一个并知道是否还有更多。
    • 你可以认为是:在第一项之前开始-> next 增加指针然后返回值或从第一项开始-> next 返回然后增加指针。在任何一种情况下,只有当整个列表被迭代时,hasNext 才为 false。
    【解决方案4】:

    当迭代器位于最后一个'n'并调用ricCrea时,hasNext将返回truenext将返回'o'。

    所以你可能想写这样的东西:

    public static String ricCrea(ListIterator<Character> it) {
        if (it.hasNext()) {
            Character c = it.next();
            if (it.hasNext()) {
                return c + ricCrea(it);
            }
        }
        return "";
     }
    

    【讨论】:

    • 您好,谢谢您的回复。在我的意大利书中写到“下一步返回迭代器位置的值,然后将迭代器移动到下一个位置”。对吗?
    • @DanieleImpagliazzo No. 返回当前位置之后的下一个值。
    【解决方案5】:

    hasnext() 方法只是让您知道列表中是否遗漏了一个字符。 next() 是获取字符值的方法。因此,haveext() 不会增加迭代器的位置。它只是告诉下一个位置是否有任何元素,您可以根据它调用 next() 或执行所需的操作。

    【讨论】:

      猜你喜欢
      • 2016-09-14
      • 1970-01-01
      • 2020-04-29
      • 2017-03-21
      • 1970-01-01
      • 2016-03-08
      • 1970-01-01
      • 2014-05-01
      • 1970-01-01
      相关资源
      最近更新 更多