【问题标题】:Java - Is Set.contains() broken on OpenJDK 6?Java - OpenJDK 6 上的 Set.contains() 是否损坏?
【发布时间】:2011-02-27 02:28:08
【问题描述】:

我遇到了一个非常奇怪的问题。我编写了一个简单的Deck 类,它代表标准的 52 张扑克牌。该类有一个方法missingCards(),它返回从牌组中抽出的所有牌的集合。如果我尝试使用 .equals() 比较两组相同的缺失卡片,我会被告知它们是不同的,如果我检查一组是否包含我知道使用 .contains() 的元素,我会返回 false .

这是我的测试代码:

    public void testMissingCards() 
{
    Deck deck = new Deck(true);
    Set<Card> drawnCards = new HashSet<Card>();
    drawnCards.add(deck.draw());
    drawnCards.add(deck.draw());
    drawnCards.add(deck.draw());
    Set<Card> missingCards = deck.missingCards();
    System.out.println(drawnCards);
    System.out.println(missingCards);
    Card c1 = null;
    for (Card c : drawnCards){
        c1 = c;
    }
    System.out.println("C1 is "+c1);
    for (Card c : missingCards){
        System.out.println("C is "+c);
        System.out.println("Does c1.equal(c) "+c1.equals(c));
        System.out.println("Does c.equal(c1) "+c.equals(c1));
    }
    System.out.println("Is c1 in missingCards "+missingCards.contains(c1));
    assertEquals("Deck confirm missing cards",drawnCards,missingCards);
}

(编辑:为了清楚起见,我在注意到测试失败后添加了两个循环。第一个循环从 drawCards 中取出一张卡片,然后检查这张卡片与 missingCards 中的每张卡片 - 它总是匹配一张,所以这张卡片必须包含在 missingCards 中。但是,missingCards.contains() 失败)

下面是它的输出示例:

[5C, 2C, 2H]
[2C, 5C, 2H]
C1 is 2H
C is 2C
Does c1.equal(c) false
Does c.equal(c1) false
C is 5C
Does c1.equal(c) false
Does c.equal(c1) false
C is 2H
Does c1.equal(c) true
Does c.equal(c1) true
Is c1 in missingCards false

我完全确定 .equals 在我的卡类上的实现是正确的,并且从输出中可以看出它确实有效!

这是怎么回事?

干杯,

皮特

【问题讨论】:

  • 有一个大括号不合适,所以你循环遍历所有卡片一次,然后将最后一张只保留在 c1 中,并检查一次。
  • 那是故意的,我非常困惑,所以我写了一些非常粗糙和准备好的测试。

标签: java set equals contains


【解决方案1】:

您忘记以与equals() 一致的方式实现hashCode() :) (即相等的对象必须返回相同的哈希码)。

【讨论】:

  • 几乎可以肯定。海报确实应该为我们发布 Card.java。
  • 感谢您的回答,我还没有实现 hashCode()。您对我如何最好地实现 hashCode 有任何提示(一张卡片的字段面和花色都是整数)?
  • Eclipse 会一键自动生成合理的 hashCode 和 equals。
  • @Peter,Effective Java 2nd version,Item 9,包含大量提示。一些快捷方式包括 Arrays.hashCode() (java.sun.com/javase/6/docs/api/java/util/…) 和 Objects.hashCode() (Guava) (guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/…) 嗯,我错过了在 cmets 中粘贴链接的更好方法吗?
【解决方案2】:

hashCode 呢?根据 Joshua Bloch 的“Effective Java”chapter 3,您应该始终同时覆盖这两者。

发布您的 Card 课程。到时候就很容易发现了。

【讨论】:

  • 这到底为什么被否决了?这与被接受的答案相同。
【解决方案3】:

请发布Deck 类的代码——至少是equals(Object)hashCode() 方法。

我的第一个猜测是你只实现了equals(),但没有实现hashCode()。如果是这种情况,请阅读 java.lang.Object 类的文档。

【讨论】:

    【解决方案4】:

    Java - Set.contains() 在 OpenJDK 6 上是否损坏?

    不,不是。

    调试 Java 的第一条规则是 99.9% 的时间是您的代码被破坏,而不是 Java 标准库。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-02-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-23
      • 1970-01-01
      • 2012-04-13
      相关资源
      最近更新 更多