【问题标题】:Why does this HashMap.get return a null?为什么这个 HashMap.get 返回 null?
【发布时间】:2011-05-21 06:49:23
【问题描述】:

我正在尝试创建一个Hashmap 来为我执行查找。但是,当我运行此测试代码时,输​​出为空。我认为这与密钥存储方式的性质有关,但我并不积极。也许这是一个类似的怪癖,比如var1 == var2 不等于,除非它们指向内存中的同一个对象,而是你必须使用var1.equals(var2)

有两个类可以测试这个。

TestCard.java

import java.util.HashMap;

public class TestCard {

     // HashMap for SpecialK Lookup
    private static HashMap<Card, Integer> specialKLookup = new HashMap<Card, Integer>();

    // Constructor
    public TestCard(){
    }

    public static void main(String[] args) {
        Card[] cards = new Card[3];
        cards[0] = new Card((short)12, (short)0);
        cards[1] = new Card((short)0, (short)1);
        cards[2] = new Card((short)5, (short)2);

        /* Build SpecialK Lookup HashMap.
         * Ace of Spades = 0
         * Ace of Hearts = 1
         * Ace of Diamonds = 2
         * Ace of Clubs = 3
         * ...
         * Two of Clubs = 51
         */
        Integer specialKCounter = 0;
        for(int i=12;i>=0;i--){
                for (int j=0;j<4;j++){
                        specialKLookup.put(new Card((short)i, (short)j), specialKCounter++);
                }
        }

        System.out.println(specialKLookup.get(cards[0]));
    }
}

Card.java

public class Card{
    private short rank, suit;

    private static String[] ranks = {"2", "3", "4", "5", "6", "7", "8", "9", "10", "Jack", "Queen", "King", "Ace"};
    private static String[] suits = {"Spades", "Hearts", "Diamonds", "Clubs"};

    //Constructor
    public Card(short rank, short suit){
        this.rank = rank;
        this.suit = suit;
    }

    // Getter and Setters
    public short getSuit(){
        return suit;
    }

    public short getRank(){
        return rank;
    }

    protected void setSuit(short suit){
        this.suit = suit;
    }

    protected void setRank(short rank){
        this.rank = rank;
    }   
}

【问题讨论】:

    标签: java hashmap


    【解决方案1】:

    类 (Card) 缺少 equals(Object)hashCode() 的正确实现

    如果没有这两个定义,它将无法正常工作。 (它编译得很好,因为这些方法都是虚拟的并且在所有对象中都是继承的,因为它们是 Object 的一部分:HashMap 无法在编译时强制执行此操作。)请参阅上面的链接以获取所需的合同。

    这两个方法都需要实现,因为hashCode决定了HashMap实现中使用的hash-bucket,equals是为了保证一个对象值相等(多个对象可以有相同的hashCode ,这就是为什么还需要equals)。请参阅Hash table 了解更一般的哈希详细信息。

    如果这些方法没有重载,则使用 Object 中定义的实现。也就是说,x.equals(y) 具有接近x == y 的语义,hashCode 为每个合约返回一个稳定的数字。这有效地使映射像 identity map 一样工作(当 Card 对象是键时):只有 完全相同的对象 可以检索先前存储的值 - 每个其他 get 都会返回空,如观察到的那样。

    编码愉快。

    【讨论】:

      【解决方案2】:

      确实是因为这个问题。

      您需要定义卡片上的相等含义,因此您需要覆盖 equalshashCode 方法。

      如果你不这样做,它假定两张牌只有在它们是相同的实例时才相等。 (与equals 的默认行为一样。)

      请注意,覆盖equalshashCode 非常重要,因为两个相等的对象必须 散列到相同的值,HashMap 才能正常工作。

      有关详细信息,请参阅Overriding equals and hashCode in Java

      【讨论】:

        【解决方案3】:

        也许这与 var1 == var2 不等于的方式类似,除非它们指向内存中的 > 相同对象,否则您必须使用 var1.equals(var2)

        几乎。如您所料,哈希映射需要一种获取对象哈希码的方法。在 Java 中,这是由 Object 实现的 hashCode method 提供的,但需要被您的 Card 类覆盖。

        *update:正如 pst 指出的,它还必须重新实现 equals。

        【讨论】:

        • 根据合同,它还必须实现equals
        【解决方案4】:

        您需要实现 hashCode 和 equals 方法,因为这允许对两个不同的对象进行相等测试,并且还有助于哈希映射存储。如果不实现这些,即使它们的属性相同,两个对象也会被视为不同的。详情请见http://www.jchq.net/certkey/0902certkey.htm

        【讨论】:

          【解决方案5】:

          卡应该覆盖equalshashCode。 看这里:http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html

          【讨论】:

            【解决方案6】:

            您必须重写 CardhashCode() 方法并使其返回相同的值,当且仅当卡片相等时 - 您也应该重写 equals()。因为这就是 HashMap 所依赖的,以便找到键引用的对象;就目前而言,正在使用的是从Object 继承的那些方法的版本,只有当您使用相同的对象作为键时才会匹配,而您正在创建新的,尽管是“相等”的。

            【讨论】:

            • 如果equals() 返回true,则hashCode() 必须相同。如果equals() 返回false,则hashCode() 的结果仍然可能相等,但也可能不同。如果hashCode() 的结果不同,equals() 必须返回 false。
            • 这个答案是不正确的,因为两个不等于对象可以具有相同的哈希码(即,“当且仅当卡片相等”的陈述是不正确的)。 Arjan 总结得很正确。
            • @SteveKuo 因此,如果我从我写的内容中删除“且仅当”,答案将不再不正确,但您的 cmets 将不再有意义。我该怎么办?
            猜你喜欢
            • 2022-12-03
            • 2018-12-10
            • 2012-02-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2013-08-09
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多