简体   繁体   中英

ContainsAll array list issue Java

So I'm trying to use the containsAll built in list method to compare two arrays

I used the contains method for single values and it works perfectly, however the contains all doesn't.

I'm making a card game so I'm checking whether a set of cards is also in another set of cards

so:

  if(this.hand.containsAll(hand.getCards())){

however this statement keeps returning false..

Here's the constructor

  private ArrayList<Card> hand;
     public Hand(ArrayList<Card> hand) {
            this();
            this.hand.addAll(hand);
        }

here's the get cards method

 public ArrayList<Card> getCards() {
        return this.hand;
    }

unsure as to why this code isn't returning true for containsAll but it's fine when done individually, is there some common concept that I haven't considered?

Any pointers would be a bonus

thank you

EDIT:

This returns true when used :

works

public boolean hasCard(Card card){
   if (this.hand.contains(card)){
       return true;
   }
}

doesn't

public boolean hasCards(Hand hand){
    if(this.hand.containsAll(hand.getCards()){
    return true
}
}

Main..

    Card one = new Card(Card.Rank.ACE, Card.Suit.CLUBS);
            Card two = new Card(Card.Rank.ACE, Card.Suit.DIAMONDS);
            Card three = new Card(Card.Rank.TWO, Card.Suit.SPADES);
            Card four = new Card(Card.Rank.SIX, Card.Suit.randSuit());
            Card five = new Card(Card.Rank.SEVEN, Card.Suit.randSuit());
            ArrayList<Card> cards = new ArrayList<>();
            cards.add(one);
            cards.add(two);
            cards.add(three);
            cards.add(four);
            cards.add(five);
            Hand h = new Hand(cards);


   Card ones = new Card(Card.Rank.ACE, Card.Suit.CLUBS);
        Card twos = new Card(Card.Rank.ACE, Card.Suit.DIAMONDS);
        Card threes = new Card(Card.Rank.TWO, Card.Suit.SPADES);
        ArrayList<Card> cards2 = new ArrayList<>();

// works
h.hasCard(five);

// doesn't
h.hasCards(h2);


        cards2.add(ones);
        cards2.add(twos);
        cards2.add(threes);
        Hand h2 = new Hand(cards2);

Try this h.hasCard(new Card(Card.Rank.ACE, Card.Suit.CLUBS)) . It fill return false. But this h.hasCard(one) returns true.

To understand why, try this: one.equals(new Card(Card.Rank.ACE, Card.Suit.CLUBS) . These are two instances of the same card, but java has no way of knowing about it. They are two different objects.

You added one to your h hand, so, when looking for that object, you find it. But searching for another object new Card(Card.Rank.ACE, Card.Suit.CLUBS) fails, because java does not know it represents the same card.

To fix this, you have to override the equals message on Card , and make it return true for objects that correspond to the same card.

Your containsAll call isn't working for the same reason: the hand contains all the cards, but they are represented by different objects. Implementing the equals method will fix that as well.

You need to override the equals method.

When you do this:

Card five = new Card(Card.Rank.SEVEN, Card.Suit.randSuit());
h.hasCard(five);

You are essentially checking (five == five) which is true. This is because the default implementation of equals() method is (from the doc ):

The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).

Now when you have h2 containing the following cards:

Card ones = new Card(Card.Rank.ACE, Card.Suit.CLUBS);
Card twos = new Card(Card.Rank.ACE, Card.Suit.DIAMONDS);
Card threes = new Card(Card.Rank.TWO, Card.Suit.SPADES);

and h the following cards:

    Card one = new Card(Card.Rank.ACE, Card.Suit.CLUBS);
    Card two = new Card(Card.Rank.ACE, Card.Suit.DIAMONDS);
    Card three = new Card(Card.Rank.TWO, Card.Suit.SPADES);
    Card four = new Card(Card.Rank.SIX, Card.Suit.randSuit());
    Card five = new Card(Card.Rank.SEVEN, Card.Suit.randSuit());

And then you do:

h.hasCards(h2);

Then you are essentially checking if ones, twos and threes are present in h . Which is false, because for instance ones is NOT == any object in h .

You can check this for yourself by printing the value of (ones == one) which will be false.

Solution:

If you override the equals() method in your Class Card something like:

@Override
public boolean equals(Object o) {

    // Check if o == itself  
    if (o == this) {
        return true;
    }

    // Check to see if o is instance of Card or not
    if (!(o instanceof Card)) {
        return false;
    }

    // typecast o to Card to compare 
    Card c = (Card) o;

    // check equality (assuming Rank and Suit to be int, else you need to change equality condition here)
    return this.Rank == c.Rank
            && this.Suit == c.Suit;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM