2

Having a little bit of trouble with the iterator next(). Can't seem to get it to work properly. I've been working on this code for a while so I was thinking another set of eyes would help.

This is my deck class with creates a list of Card objects, I'm trying to make a method to grab the next Card in the list starting with the first one:

package blackjack;

import blackjack.Card.Rank;
import blackjack.Card.Suit;
import java.util.*;

public class Deck {

public ArrayList<Card> cards = new ArrayList<>();
int i;
Card next;

public Deck() {
    initializeDeck();

}

public void printDeck() {
    for (Card c: cards)
        System.out.println(c);
}

private void initializeDeck() {
    for (Suit suit : Suit.values()) {
        for (Rank rank : Rank.values()) {
            cards.add(new Card(rank, suit));
        }
    }
}

public Card getNextCard() {
    if (cards.listIterator().hasNext() != true) {
        getNextCard();
    }
    else {
        next = cards.listIterator().next();
    }
      return next; 
}
}

This is my main class where I call the getNextCard() and what I'm thinking it should do is print the first and then the next Card in the list but what it's doing is printing the first Card twice.

package blackjack;

import java.util.*;

public class BlackJack {

public static void main(String[] args) {
    Deck deck = new Deck();
    System.out.println(deck.getNextCard());
    System.out.println(deck.getNextCard());
    }

}

Thanks in advance for any help!

2
  • 3
    Love your subtil infinite loop in getNextCard() ! Commented Apr 26, 2013 at 19:57
  • looks like you're getting a new iterator each time Commented Apr 26, 2013 at 19:57

3 Answers 3

5

In your getNextCard() method, you're creating an iterator every time it's called. Iterators always start at index 0 (although there is a listIterator(index) method), but you shouldn't need it.

Option 1: Keep track of the iterator, and use the same iterator each time. However, this has an important shortcoming not pointed out by anyone else yet. From the Javadoc:

The iterators returned by this class's iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator's own remove or add methods, the iterator will throw a ConcurrentModificationException.

Translation: If you modify the list in any way outside of the iterator (say, by adding a card to the end of the list), then your iterator breaks. This leads us to option 2:

Option 2: Keep a counter of the index you returned last, and simply return that each time. Something like:

public class Deck {

public ArrayList<Card> cards = new ArrayList<>();
Card next;
int currentCardIndex = -1;

/* The initialization stuff you have above */

public Card getNextCard() {

    currentCardIndex++;

    // If we're at the end, go back to the beginning
    if (currentCardIndex >= cards.size()) {
        currentCardIndex = 0;
    }

    return (next = cards.get(currentCardIndex));
}

And finally Option 3: (not advised): If you really wanted to, you could catch the ConcurrentModificationException and generate a new iterator at that point, but there's not really a reason to unless you need some iterator-specific feature. (The get() call is just as fast as an interator - both are constant time).

Sign up to request clarification or add additional context in comments.

2 Comments

Haven't tried it yet because I have to go to work but your second alternative is how I'm going to do it. Thanks!
Yep, that would be advisable. Good luck!
3

You need to save the iterator returned by cards.listIterator().

Your code creates a new one each time, meaning you always get the first element.

Comments

0

You always get the first card because you are creating a new iterator each time you call the getNextCard () method. The line

next = cards.listIterator().next();

will always create a new iterator. What you want to do would look like (assuming you want to create a new ListIterator instance each time you have reached the last card of the deck):

private ListIterator<Card> myIterator = null;

public Card getNextCard() {
    if (myIterator == null || !myIterator.hasNext ()) {
        myIterator = cards.listIterator ();
    }

    return myIterator.next(); 
}

2 Comments

Just tried that line of code and it still prints the same thing
@NotaNoobForever Yeah I had made a mistake. I fixed the return statement with the correct code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.