John
John

Reputation: 13

How to iterate through a list of objects with a specific variable?

So I have a Deck class which holds a deck list which creates 52 Card objects and stores them in an array list. I can iterate through that deck list using the iterator I have shown but now I want to know how I can modify the iterator to iterate through the deck list for certain variables. For example, I just want to iterate through all the Spades or all the Kings. Thanks.

fyi: The DeckIterator is within the Deck class I just didn't know how to format the code on stack. Apologies.

    public class Card implements Serializable, Comparable<Card> {    
        static final long serialVersionUID = 100;

        Suit suit;
        Rank rank;

        public Card(Rank rank, Suit suit){
            this.rank = rank;
            this.suit = suit;
        }
    }

    public enum Rank {
        TWO(2), THREE(3), FOUR(4), FIVE(5), 
        SIX(6), SEVEN(7), EIGHT(8), NINE(9),
        TEN(10), JACK(10), QUEEN(10), KING(10), ACE(11);

        int value;

        public static Rank valuesList[] = Rank.values();

        Rank(int value){
            this.value = value;
        }

        public int getValue() {
            return this.value;
        }

        public Rank getNext() {
            if (this.value == 11) {
                return valuesList[0];
            } else {
                return valuesList[ordinal() + 1];
            }
        }

        public int getOrdinal() {
            return ordinal();
        } 
    }

    public enum Suit {
        CLUBS, DIAMONDS, HEARTS, SPADES;

        public static Suit suitsList[] = Suit.values();

        public Suit randomSuit() {
            Random random = new Random();
            return suitsList[random.nextInt(4)];
        }
    }

    private class DeckIterator<Card> implements Iterator<Card> {
        private final Deck deck;
        private int pos = 0;

        public DeckIterator(Deck deck) {
            this.deck = deck;
            pos = 0;
        }

        @Override 
        public boolean hasNext() {
            return pos < deck.size();
        }

        @Override 
        public Card next() {
            return (Card) deck.deck.get(pos++);
        }

        @Override
        public void remove() {
            deck.deck.remove(pos);
        }
    }

Upvotes: 1

Views: 1025

Answers (2)

Andrew
Andrew

Reputation: 49606

I just want to iterate through all the Spades or all the Kings.

Here we are.

new DeckIterator(deck, card -> Rank.KING.equals(card.getRank()));
new DeckIterator(deck, card -> Suit.SPADES.equals(card.getSuit()));

I fully agree with @rzwitserloot's answer, and will extend his post with my iterator which takes a Predicate to form another iterator that runs over only selected elements.

class DeckIterator implements Iterator<Card> {

    private final Iterator<? extends Card> iterator;

    public DeckIterator(Deck deck, Predicate<Card> predicate) {
        iterator = deck.deck.stream().filter(predicate).iterator();
    }

    @Override
    public boolean hasNext() {
        return iterator.hasNext();
    }

    @Override
    public Card next() {
        return iterator.next();
    }

    @Override
    public void remove() {
        iterator.remove();
    }

}

Upvotes: 2

rzwitserloot
rzwitserloot

Reputation: 102813

You can't; not with this data structure. You have a few options:

  1. iterate through everything, but abort this iteration at the top if it doesn't match your required state. For example:

    for (Card card : deck) {
        if (card.getRank() != Rank.ACE) continue;
        /* code to deal with aces here */
    }
    
  2. You use stream API constructs to filter. You did not include your Deck class in your paste, but assuming deck.deck is some sort of java.util.List, you can for example do:

    deck.deck.stream().filter(x -> x.getRank() == Rank.ACE).iterator()
    

which will give you an iterator that iterates through only the aces.

Upvotes: 4

Related Questions