具有相同字段的自定义对象集不会被计为“等于”

时间:2017-07-15 14:01:24

标签: java

我正在写一个纸牌游戏,并有一个Card类和一个Playable类。 Playables代表玩家可能选择为特定游戏状态玩牌的牌组。我正在测试一个获得合法Playables集合的函数。我的方法是手动构造正确的答案,然后断言它等于我的函数返回的集合。

这是我的设置功能。 cardsList<Card>类型的私有成员。

@Before
    public void setup() {
        cards = new ArrayList<Card>();
        cards.add(new Card(Suit.HEARTS, CardValue.ACE));
        cards.add(new Card(Suit.DIAMONDS, CardValue.ACE));
        cards.add(new Card(Suit.CLUBS, CardValue.ACE));
        cards.add(new Card(Suit.SPADES, CardValue.ACE));
        cards.add(new Card(Suit.CLUBS, CardValue.EIGHT));
        cards.add(new Card(Suit.HEARTS, CardValue.EIGHT));
        cards.add(new Card(Suit.SPADES, CardValue.EIGHT));
        cards.add(new Card(Suit.DIAMONDS, CardValue.SIX));
        cards.add(new Card(Suit.SPADES, CardValue.SIX));
        hand = new Hand(cards);
    }

以下是测试用例。

@Test
public void testGetLegalDoubles() throws Exception {
    Card toBeat = new Card(Suit.CLUBS, CardValue.NINE);
    Set<Playable> correct = new HashSet<Playable>();
    Collection<Card> doubles1 = Arrays.asList(new Card[] {cards.get(0), cards.get(1)});
    Collection<Card> doubles2 = Arrays.asList(new Card[] {cards.get(0), cards.get(2)});
    Collection<Card> doubles3 = Arrays.asList(new Card[] {cards.get(0), cards.get(3)});
    Collection<Card> doubles4 = Arrays.asList(new Card[] {cards.get(1), cards.get(2)});
    Collection<Card> doubles5 = Arrays.asList(new Card[] {cards.get(1), cards.get(3)});
    Collection<Card> doubles6 = Arrays.asList(new Card[] {cards.get(2), cards.get(3)});
    Playable move1 = new Playable(doubles1, PlayMode.DOUBLES, cards.get(0));
    Playable move2 = new Playable(doubles2, PlayMode.DOUBLES, cards.get(0));
    Playable move3 = new Playable(doubles3, PlayMode.DOUBLES, cards.get(0));
    Playable move4 = new Playable(doubles4, PlayMode.DOUBLES, cards.get(1));
    Playable move5 = new Playable(doubles5, PlayMode.DOUBLES, cards.get(1));
    Playable move6 = new Playable(doubles6, PlayMode.DOUBLES, cards.get(2));
    correct.add(move1);
    correct.add(move2);
    correct.add(move3);
    correct.add(move4);
    correct.add(move5);
    correct.add(move6);
    Set<Playable> doubles = hand.getLegalNOfAKind(2, toBeat);
    assertEquals(doubles, correct);
}

此测试用例失败,但我尝试打印出doublescorrect的内容并且匹配 - 我的toString() Playable实现显示了所有字段这些课程。我还为equals()hashCode()覆盖了CardPlayable,如下所示(由Eclipse自动生成)。

Card

    @Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((suit == null) ? 0 : suit.hashCode());
    result = prime * result + ((value == null) ? 0 : value.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Card other = (Card) obj;
    if (suit != other.suit)
        return false;
    if (value != other.value)
        return false;
    return true;
}

Playable

    @Override
public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result + ((cards == null) ? 0 : cards.hashCode());
    result = prime * result + ((highCard == null) ? 0 : highCard.hashCode());
    result = prime * result + ((playmode == null) ? 0 : playmode.hashCode());
    return result;
}

@Override
public boolean equals(Object obj) {
    if (this == obj)
        return true;
    if (obj == null)
        return false;
    if (getClass() != obj.getClass())
        return false;
    Playable other = (Playable) obj;
    if (cards == null) {
        if (other.cards != null)
            return false;
    } else if (!cards.equals(other.cards))
        return false;
    if (highCard == null) {
        if (other.highCard != null)
            return false;
    } else if (!highCard.equals(other.highCard))
        return false;
    if (playmode != other.playmode)
        return false;
    return true;
}

我的怀疑是,我正在构建correct的方式还有些问题 - 也许我是如何引用cards的?

1 个答案:

答案 0 :(得分:-2)

根据其他评论,全面了解这一点很棘手。看起来你将一系列卡片传递给Playable构造函数,你是否将它们作为数组存储在Playable中?如果是这样,这可能是Playable.equals

中的问题
} else if (!cards.equals(other.cards))
    return false;

永远是假的(例子);

final Integer[] is1 = new Integer[]{1};
final Integer[] is2 = new Integer[]{1};
Assert.assertFalse(is1.equals(is2));

集合将为您节省一些工作,因此您可以将卡存储为Playable中的ArrayList;

public class Playable {
    List<Card> cards;

    public Playable (Card[] cards, other params....) {
        ....
        this.cards = new ArrayList();
        for (Card card : cards) { this.cards.add(card); }
    }

并且在你的equals中有类似的东西(如果你想在列表中使用.equals,你需要先对它们进行排序):

    public boolean equals () {
       .....
       .....
       if (cards.containsAll(other.cards) && other.cards.containsAll(cards) {
           return true;

我建议你为card.equals()做一个简单的测试用例,确保它有效。 作为一个观察,它在这里并不重要,因为你使用枚举,但使用.equals而不是==

总是一个好主意
if (suit != other.suit)

会更好地写成

if (!suit.equals(other.suit))

希望这有帮助!