【问题标题】:Getting a weird NoSuchElementException得到一个奇怪的 NoSuchElementException
【发布时间】:2018-02-13 15:08:15
【问题描述】:

我们正在尝试编译我们的程序,但我们不断收到NoSuchElementException。任何人都知道为什么会不断发生这种情况?提前致谢。下面我将附上我们实现异常的代码和main方法。

编辑 - 整个代码如下:

import java.util.Iterator;
import edu.princeton.cs.algs4.*;

public class RandomQueue<Item> implements Iterable<Item> {
    private Item[] queue;
    private int N;
    private int size;

    // Your code goes here.
    public RandomQueue() { // create an empty random queue
        N = 0;
        size = 2;
        queue = (Item[]) new Object[size];
    }

    public boolean isEmpty() {// is it empty?
        if(N == 0) {
            return true;
        } else {
            return false;
        }
    }

    public int size() {// return the number of elements
        return size;
    }

    public void resizeArray() {
        if(3/4*size < N) {
            size = size*2;
            Item[] queueUpdated = (Item[]) new Object[size];
            for(int i = 0; i < queue.length; ++i) {
                queueUpdated[i] = queue[i];
            }
            queue = queueUpdated;
        } else if (N < 1/4*size) {
            size = size/2;
            Item[] queueUpdated = (Item[]) new Object[size];
            for(int i = 0; i < size-1; ++i) {
                queueUpdated[i] = queue[i];                 
            }
            queue = queueUpdated;
        }

    }


    public void enqueue(Item item) {// add an item
        if(N < queue.length) {
            queue[N++] = item;
            resizeArray();
        }
    }

    public Item sample(){ // return (but do not remove) a random item
        if(isEmpty()) {
            throw new RuntimeException("No such elements");
        } else {
            return queue[StdRandom.uniform(N)];
        }
    }

    public Item dequeue(){ // remove and return a random item
        if(isEmpty()) {
            throw new RuntimeException("Queue is empty");
        } else {
            System.out.println(N);
            int indexFraArray = StdRandom.uniform(N);
            Item i = queue[indexFraArray];
            queue[N] = null;
            queue[indexFraArray] = queue[N--];
            resizeArray();
            return i;
        }
    }

    private class RandomQueueIterator<E> implements Iterator<E> {
        int i = 0;
        public boolean hasNext() {
            return i < N;
        }
        public E next() {
            if (!hasNext()) {
                throw new java.util.NoSuchElementException(); // line 88
            }
            i++;
            return (E) dequeue();
        }
        public void remove() {
            throw new java.lang.UnsupportedOperationException();
        }
    }

    public Iterator<Item> iterator() { // return an iterator over the items in 
        random order
        return new RandomQueueIterator();
    }


    // The main method below tests your implementation. Do not change it.
    public static void main(String args[]) {
        // Build a queue containing the Integers 1,2,...,6:
        RandomQueue<Integer> Q = new RandomQueue<Integer>();
        for (int i = 1; i < 7; ++i) Q.enqueue(i); // autoboxing! cool!

        // Print 30 die rolls to standard output
        StdOut.print("Some die rolls: ");
        for (int i = 1; i < 30; ++i) StdOut.print(Q.sample() +" ");
        StdOut.println();

        // Let's be more serious: do they really behave like die rolls?
        int[] rolls= new int [10000];
        for (int i = 0; i < 10000; ++i)
            rolls[i] = Q.sample(); // autounboxing! Also cool!
        StdOut.printf("Mean (should be around 3.5): %5.4f\n", StdStats.mean(rolls));
        StdOut.printf("Standard deviation (should be around 1.7): %5.4f\n",
                StdStats.stddev(rolls));

        // Now remove 3 random values
        StdOut.printf("Removing %d %d %d\n", Q.dequeue(), Q.dequeue(), Q.dequeue());
        // Add 7,8,9
        for (int i = 7; i < 10; ++i) Q.enqueue(i);
        // Empty the queue in random order
        while (!Q.isEmpty()) StdOut.print(Q.dequeue() +" ");
        StdOut.println();

        // Let's look at the iterator. First, we make a queue of colours:
        RandomQueue<String> C= new RandomQueue<String>();
        C.enqueue("red"); C.enqueue("blue"); C.enqueue("green"); 
        C.enqueue("yellow");

        Iterator<String> I = C.iterator();
        Iterator<String> J = C.iterator();

        StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");

        StdOut.print("\nEntire second shuffle: ");
        while (J.hasNext()) StdOut.print(J.next()+" ");

        StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142
    }
}

I compile in cmd and this is the error I get

错误发生在这里: enter image description here

这里: enter image description here

【问题讨论】:

  • 至少添加 Stacktrace 和抛出异常的提示。
  • 嘿伙计 - 感谢您的关注。我现在已经编辑了这篇文章,所以它现在包含了整个代码。
  • 还有一些我在代码中出现错误的图像
  • 第 88 行是哪一行?您的堆栈跟踪似乎说异常发生在那里。第 142 行呢?
  • 我附上了他们的一些照片:)

标签: java algorithm exception queue nosuchelementexception


【解决方案1】:

您的迭代器正在修改您的集合。这至少是非标准的,似乎让你自己感到困惑。

您正在队列 @9​​87654321@ 上创建两个迭代器,此时其中有 4 个元素:

    Iterator<String> I = C.iterator();
    Iterator<String> J = C.iterator();

你向前一个迭代器询问两个元素:

    StdOut.print("Two colours from first shuffle: "+I.next()+" "+I.next()+" ");

这会通过这一行移除(出列)这两个元素:

        return (E) dequeue();

现在您的队列中有 2 个元素。 N 是 2。

您尝试在此处删除剩余的 2 个元素:

    StdOut.print("\nEntire second shuffle: ");
    while (J.hasNext()) StdOut.print(J.next()+" ");

但是,在删除一个元素后,J.i 为 1,N 为 1,因此迭代器 J 认为队列已用完,只为您提供这一个元素。还剩一个。 N 是 1。但您尝试删除另外两个元素:

    StdOut.println("\nRemaining two colours from first shuffle: "+I.next()+" "+I.next()); // line 142

这注定会失败。幸运的是它确实如此。 next 调用hasNext,后者依次比较:

        return i < N;

I.i 是 2(因为我们之前从 I 中获取了 2 个元素)并且 N 是 1,所以 hasNext 返回 false,这会导致 next 抛出异常。

解决方案很简单,也可能没那么简单:你的迭代器不应该从队列中移除任何元素,只需要按顺序返回元素。

真正的答案是:您应该学习使用调试器。这对您来说将是一笔不错的投资。

【讨论】:

  • 感谢您的帮助。顺便说一句,我忘了提到我不允许更改 main 方法。虽然,根据您的回答,我是否应该更改私有内部类中的部分,以便它按顺序返回元素?它是否包括删除出队部分?
  • 是的,您需要删除 dequeue 调用,但您还需要替换其他内容,以便该方法可以返回某些内容。您可以利用在内部类中可以在外部类中使用queue 数组这一事实。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-03-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多