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

为集合定制的迭代器会为每个循环抛出异常

戚鸿福
2023-03-14

我正在尝试为我制作的Set编写一个自定义的迭代器。我对Interface Iterable的合同有点困惑。它有三个方法:Next()、hasNext()和拿下()。我的设置是不可变的,所以我计划为删除()方法抛出一个Unsupport tedoperationException。它也被称为“延迟生成”,即元素不存储html" target="_blank">内存中,而是在需要时创建,但这不是这里也不是那里。

Iterator的Next()方法的javadoc如下:

E next()

Returns the next element in the iteration.
Returns:
the next element in the iteration
Throws:
NoSuchElementException - if the iteration has no more elements

对于hasNext()来说:

boolean 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.)

按照这些规则,我开始实现我的集合和迭代器,得到:

import java.util.AbstractSet;
import java.util.Iterator;

public class PrimesBelow extends AbstractSet<Integer>{

    int max;
    int size;

    public PrimesBelow(int max) {
        this.max = max;
    }

    @Override
    public Iterator<Integer> iterator() {
        return new SetIterator<Integer>(this);
    }

    @Override
    public int size() {
        if(this.size == -1){
            System.out.println("Calculating size");
            size = calculateSize();
        }else{
            System.out.println("Accessing calculated size");
        }
        return size;
    }

    private int calculateSize() {
        int c = 0;
        for(Integer p: this)
            c++;
        return c;
    }

    public static void main(String[] args){
        PrimesBelow primesBelow10 = new PrimesBelow(10);
        for(int i: primesBelow10)
            System.out.println(i);
        System.out.println(primesBelow10);
    }
}

.

import java.util.Iterator;
import java.util.NoSuchElementException;

public class SetIterator<T> implements Iterator<Integer> {
    int max;
    int current;
    public SetIterator(PrimesBelow pb) {
        this.max= pb.max;
        current = 1;
    }

    @Override
    public boolean hasNext() {
        if(current < max) return true;
        else return false;
    }

    @Override
    public Integer next() {
        while(hasNext()){
            current++;
            if(isPrime(current)){
                System.out.println("returning "+current);
                return current;
            }
        }
        throw new NoSuchElementException();
    }

    private boolean isPrime(int a) {
        if(a<2) return false;
        for(int i = 2; i < a; i++) if((a%i)==0) return false;
        return true;
    }
}

这在我看来很好,Next()返回下一个值并在没有更多值时抛出异常。如果有更多值要迭代,hasNext()应该返回true,否则返回false。然而,主循环的输出是这样的:

returning 2
2
returning 3
3
returning 5
5
returning 7
7
Exception in thread "main" java.util.NoSuchElementException
    at SetIterator.next(SetIterator.java:27)
    at SetIterator.next(SetIterator.java:1)
    at PrimesBelow.main(PrimesBelow.java:38)

因此,在for-each循环中似乎没有处理异常。如何编写可以使用的自定义迭代器以使其正常工作?我尝试返回null而不是抛出异常,但这只会产生一个NullPointerException。

当迭代器完成时,我应该返回null,还是抛出异常?Javadoc说Next()应该抛出一个Exception,但是当我将鼠标悬停在Eclipse中的overriden方法Next()上时,签名不会显示抛出NoSuchElementException,所以我对合约所说的非常困惑。完成后返回null对我来说似乎很奇怪,因为集合可能包含空元素。

谢谢你的帮助。

共有2个答案

莫逸仙
2023-03-14

假设代码返回的最后一个素数是7。然后当前的将是7,这显然是

您需要验证hasNext()中是否有额外的素数可用。

仲孙翔飞
2023-03-14

改变

while(hasNext()) {
    //...
}
throw new NoSuchElementException();

if(hasNext()) {
    //...
} else {
    throw new NoSuchElementException();
}
 类似资料:
  • 考虑这个简单的C++函数来计算数组的前缀和: 它是4个融合的UOP1,这个CPU可以支持4个融合的OPs/周期。 有通过和携带的依赖链,每个都是一个循环,但是这些UOP可以到4个ALU端口中的任何一个,所以似乎不太可能冲突。融合的需要转到p6,这是一个更令人担忧的问题,但我只测量到p6的1.1 UOPS/迭代。这将解释每次迭代1.1个循环,但不是1.4个循环。如果我将循环展开2倍,端口压力会低得多

  • 迭代器无效是如何处理的,而不是循环? 例如,这段代码不起作用,因为迭代器在插入后无效: 但是,如果我用这个for循环替换while循环,它会正确编译和运行: 为什么for循环有效而while循环无效?

  • 问题内容: 在Java中为集合的集合设计一个迭代器。迭代器应隐藏嵌套,使您可以迭代属于所有集合的所有元素,就像使用单个集合一样 问题答案: 这是一个可能的实现。请注意,我没有执行remove():

  • 问题内容: 我想了解更多有关的信息,所以如果我错了,请纠正我。 迭代器是一个对象,该对象具有指向下一个对象的指针,并作为缓冲区或流(即,链表)读取。它们特别有效,因为它们所做的只是通过引用而不是使用索引来告诉您下一步是什么。 但是我仍然不明白为什么会发生以下行为: 经过迭代器()的第一个循环后,就好像它已被消耗并且留空,因此第二个循环()不输出任何内容。 但是,我从未为变量分配新值。 循环幕后到底

  • 如何在迭代中更改python迭代器? 例如: 此打印: 我想打印: 编辑:抱歉,这个问题让人们感到困惑。我对为什么当我在for循环中尝试更改迭代器时,for循环在下一次迭代中忽略它很感兴趣。 其他人已经提交了一个答案来清除我的困惑。范围创建一个列表,然后for循环将迭代器分配给列表中的下一个变量。

  • 问题内容: 我有下面的代码: 有谁对我如何延迟循环中的每个循环的建议?假设代码在每次迭代完成后等待10秒。我试过了,但没有设法解决。 问题答案: 您可以设置超时时间,以增加代码间隔,如下所示: 因此,第一个立即运行(间隔* 0为0),第二个在十秒钟后运行,依此类推。 您需要在中作为最终参数发送,以便将其值绑定到function参数。否则,尝试访问数组值将超出范围,您将获得。