【问题标题】:Why does this HashMap.get return a null?为什么这个 HashMap.get 返回一个空值?
【发布时间】:2022-12-03 01:10:41
【问题描述】:

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

有两个类可以对此进行测试。

测试卡.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]));
    }
}

卡片.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是为了保证一个对象是value-equals(多个对象可以有相同的hashCode,即为什么还需要 equals)。有关更多一般哈希详细信息,请参阅Hash table

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

    快乐的编码。

    【讨论】:

      【解决方案2】:

      确实是因为这个问题。

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

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

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

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

      【讨论】:

        【解决方案3】:

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

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

        *更新:正如 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】:

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

            【讨论】:

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