当前位置: 首页 > 知识库问答 >
问题:

迭代器接口

太叔逸春
2023-03-14

我有一个大学作业,要求我实现一个实现Iterator接口的内部类。迭代器适用于单链表超类。

当前我的内部类如下所示:

private class ListIterator implements Iterator<V>{

    Node temp;
    boolean nextCalled = false;

    ListIterator(Node fo){
        this.temp = fo;
    }

    @Override
    public boolean hasNext() {
        if(temp != null){
            return true;
        }
        return false;
    }

    @Override
    public V next() {
        nextCalled = true;
        return temp.getReprValue();
    }

    @Override
    public void remove() {
        if(nextCalled && hasNext()){
            nextCalled = false;
            removeElement(temp.getReprKey());
            temp = temp.getNext();
        }

    }

}

现在我的问题是,即使列表实际上为空,hasNext()方法也会返回true。其他一切似乎都起作用了。我可能忽略了某个地方的逻辑缺陷,但我自己找不到。

共有3个答案

柏正平
2023-03-14

如果当前节点(temp)不是null,则hasNext返回true。

如果您的链表实现使用头节点,那么构造函数总是收到fo=null和hasNext将返回true,即使列表为空。您应该在实现中考虑这一事实。

根据你的代码,似乎

ListIterator(Node fo){
    this.temp = fo.getNext();
}

可能会成功(如果header.getNext()==null为空列表)。

花阳秋
2023-03-14

您需要跟踪您在列表中的位置,实现光标,或者如果链接列表中的节点知道它们的下一个元素,只需询问它们是否有下一个元素。当光标大于长度/节点没有下一步时,在hasNext()中返回false。

在您的hasNext()方法中执行所有这些操作。请记住,如果hasNext()为false,则让next()引发异常是可以的,因此您需要确保这是它引发异常的唯一时间。

由于我不知道列表的底层数据结构,我无法告诉您哪一个更好。

方树
2023-03-14

更改了您的实现以反映Iterator合约需要的内容。您需要记住,您需要能够遍历集合的所有元素,即Next()应该从第一个元素开始,并且在每次调用之后,它必须将当前的下一个元素更改为列表中的下一个元素,或者如果没有,则抛出异常。

阅读Iterator接口文档以理解您需要实现它并从那里开始的方式是很好的。

private class ListIterator implements Iterator<V> {
    private Node next;
    private boolean alreadyDeleted = false;

    ListIterator(Node node){
        this.next = node;
    }

    @Override
    public boolean hasNext() {
        // because next is the current element. We need to iterate over all the elements
        // from the collection.
        return next != null;
    }

    @Override
    public V next() {
        if (next == null) {
           throw new NoSuchElementException();
        }

        Node current = next;

        this.next = current.getNext();
        this.alreadyDeleted = false; // it's better to try to elimate this state variable. You can try to do in another way, if yours removeElement returns something

        return current;
    }

    @Override
    public void remove() {
        if (alreadyDeleted || next == null) {
           throw new IllegalStateException();
        }
        removeElement(next.getReprKey());
        this.alreadyRemoved = true;
    }

}
 类似资料:
  • 迭代器 乍看来,迭代器似乎很直观。但凑近了看,你会发现标准STL容器提供了四种不同的迭代器:iterator、const_iterator、reverse_iterator和const_reverse_iterator。很快你会注意到在这四种类型中,容器的insert和erase的某些形式只接受其中一种。那是问题的开始。为什么有四种迭代器?它们之间的关系是什么?它们可以互相转化吗?在调用算法和ST

  • For freedom Christ has set us free. Stand firm, therefore, and do not submit again to a yoke of slavery. 基督释放了我们,叫我们得以自由,所以要站立得稳,不要再被奴仆的轭挟制。(GALATIANS 5:1) 迭代器 迭代,对于读者已经不陌生了,曾有专门一节来讲述,如果印象不深,请复习《迭代》。

  • 在Rust中,迭代器共分为三个部分:迭代器、适配器、消费者。 其中,迭代器本身提供了一个惰性的序列,适配器对这个序列进行诸如筛选、拼接、转换查找等操作,消费者则在前两者的基础上生成最后的数值集合。 但是,孤立的看这三者其实是没有意义的,因此,本章将在一个大节里联系写出三者。 迭代器、适配器、消费者

  • 正如我们之前学到的,在Python中我们可以使用“for”循环来迭代出对象中的内容: >>> for value in [0, 1, 2, 3, 4, 5]: ... print(value) ... 0 1 4 9 16 25 可以使用“for”循环(迭代)的对象称为迭代器。因此,一个迭代器也就是一个遵循了迭代协议的对象。 内置函数“iter”可以用来创建一个迭代对象,这时使用“next”函数

  • 我们已经知道,可以直接作用于for循环的数据类型有以下几种: 一类是集合数据类型,如list、tuple、dict、set、str等; 一类是generator,包括生成器和带yield的generator function。 这些可以直接作用于for循环的对象统称为可迭代对象:Iterable。 可以使用isinstance()判断一个对象是否是Iterable对象: >>> from coll

  • 从for循环讲起 我们在控制语句里学习了Rust的for循环表达式,我们知道,Rust的for循环实际上和C语言的循环语句是不同的。这是为什么呢?因为,for循环不过是Rust编译器提供的语法糖! 首先,我们知道Rust有一个for循环能够依次对迭代器的任意元素进行访问,即: for i in 1..10 { println!("{}", i); } 这里我们知道, (1..10) 其本身