Question

The purpose of the method removeDuplicate(ArrayList<Card> l) is that removing the duplicated object based on the attribute card_value in class Card and then add them to an ArrayList and return the arr.

But my program return an error: NoSuchElementException at the line

dum.add((Card) it.next());

I have no idea what's going on here because I print out the object that returned by the next() method, it prints out perfectly.

Someone please show me why I get mistake in the implementation below:

private ArrayList<Card> removeDuplicate(ArrayList<Card> l){
    int end = l.size();
    Set<Card> set = new HashSet<>();

    for(int i = 0; i < end; i++){
        set.add(l.get(i));
    }
    ArrayList<Card> dummy = new ArrayList<>();
    Iterator it = set.iterator();
    while(it.hasNext()){
        System.out.println(it.next());
        dummy.add((Card) it.next());
    }

    return dummy;
}

And these are override methods:

@Override
    public int hashCode() {
        int hash = 5;
        hash = 97 * hash + this.card_value;
        return hash;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj == this){
            return true;
        }
        if (!(obj instanceof Card)){
            return false;
        }
        Card other = (Card) obj;
        return (this.card_value == other.card_value);
    }
Was it helpful?

Solution

You are calling .next() twice. next() fetches the next element in the iterator but you only check hasNext() before the first one.

Change

while(it.hasNext()){
    System.out.println(it.next());
    dummy.add((Card) it.next());
}

to

while(it.hasNext()){
    Card nextCard = (Card) it.next();
    System.out.println(nextCard);
    dummy.add(nextCard);
}

OTHER TIPS

Here you can see the source code of the next() method from java Iterator. It looks something like this:

public E next() {
    checkForComodification();
    try {
        int i = cursor;
        E next = get(i);
        lastRet = i;
        cursor = i + 1;
        return next;
    } catch (IndexOutOfBoundsException e) {
        checkForComodification();
        throw new NoSuchElementException();
    }
}

As you can see, if you are out of the array a NoSuchElementException will be thrown. So calling next() twice without checking before each call if elements are still available by using hasNext() will have the behaviour you described.

Your while() should be replaced with:

while(it.hasNext()) {
    dummy.add((Card) it.next());
}

But if you really want the print-out as you have it, just change it to:

while (it.hasNext()) {
    Card card = (Card)it.next();
    System.out.println(card);
    dummy.add(card);
}

The second approach is the better way to go when you need to use an object more than once in a method or loop if the method called may be expensive.

It.next() returns the next item.

What you do in your code is calling it.next() twice

because next() moves on the pointer each time, so when you print it out, it will print the last one, then try to move on again the line after

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top