简体   繁体   中英

TreeSet does not properly add distinct data

I am trying to test a class for a test-assignment poker-game in which it is only important to determine the validity or value of particular hands.

My PokerHand object contains a TreeSet<Card> . I thought this would be an ideal data-structure since doubles are not allowed, and it automagically sorts it with red-black tree algorithm.

The problem however, is that it appears to have some side-effects that I am not yet aware of. I understand that doubles will not be added to a TreeSet , but in my tests I make sure not to. Instead I noticed that it will not add new Card objects to the TreeSet as soon as the number fields are equal, but not the type.

This is the equals method for a Card

@Override
public boolean equals(Object obj) {
    if (obj == null) {
        return false;
    }
    if (getClass() != obj.getClass()) {
        return false;
    }

    final Card other = (Card) obj;

    return this.type == other.type && this.number == other.number;
}

This is the test, adding various cards...

@Test
public void testOnePair() {
    hand.addCard(new Card(3, Card.CARD_TYPE.SPADES));
    hand.addCard(new Card(8, Card.CARD_TYPE.CLUBS));
    hand.addCard(new Card(10, Card.CARD_TYPE.HEARTS));
    hand.addCard(new Card(14, Card.CARD_TYPE.SPADES));
    hand.addCard(new Card(14, Card.CARD_TYPE.CLUBS));

    assertEquals("One Pair", this.hand.getValue());
}

What appears to be happening is that the last Card is not added, so the size of the TreeSet effectively remains 4 , even though the cards are clearly distinct. It does not even consult the equals method.

It does however reach the compareTo method.

@Override
public int compareTo(Object t) {
    if (t.getClass().equals(this.getClass())) {
        Card otherCard = (Card)t;

        if (otherCard.equals(this)) {
            return 0;
        }

        return this.number - otherCard.number;
    }
    else {
        throw new ClassCastException("Cannot convert " + t.getClass().toString() + " to Card");
    }
}

It has been a while since I've gotten back into Java 8 and maybe I'm just clearly overseeing something. I hope somebody can help me forward with this.

I've always been reluctant to ask questions here. Solved this as soon as I submitted it... Wanted to share this with you. TreeSet only cares about the compareTo method. So I changed it to be the following.

@Override
public int compareTo(Object t) {
    if (t.getClass().equals(this.getClass())) {
        Card otherCard = (Card)t;

        if (this.number == otherCard.number) return this.type.compareTo(otherCard.type);

        return this.number - otherCard.number;
    }
    else {
        throw new ClassCastException("Cannot convert " + t.getClass().toString() + " to Card");
    }
}

This solved it, because now the comparable contract is "aware" of the type properties.

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