Reputation: 13
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
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
Reputation: 102813
You can't; not with this data structure. You have a few options:
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 */
}
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