得到一个奇怪的NoSuchElementException

时间:2018-02-13 15:08:16

标签: java algorithm exception queue nosuchelementexception

我们正在尝试编译我们的程序,但我们不断获得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

1 个答案:

答案 0 :(得分:1)

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

您正在队列C上创建两个迭代器,目前其中包含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抛出异常。

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

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