为什么这个HashMap.get返回null?

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

有两个类可以测试它。

TestCard.java

 import java.util.HashMap; public class TestCard { // HashMap for SpecialK Lookup private static HashMap specialKLookup = new HashMap(); // 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; } } 

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

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

这两个方法都需要实现,因为hashCode确定HashMap实现中使用的hash-bucket, equals是确保一个对象是value-equals(多个对象可以具有相同的hashCode ,这也是为什么还需要equals ) 。 有关更多常规哈希详细信息,请参阅哈希表 。

如果这些方法没有重载,则使用Object中定义的实现。 也就是说, x.equals(y)具有near- x == y语义, hashCode每个合约返回一个稳定的数字。 这有效地使地图像身份地图一样工作(当Card对象是键时):只有完全相同的对象才能检索先前存储的值 – 每个其他get将返回null,如所观察到的那样。

快乐的编码。

确实正是因为这个问题。

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

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

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

有关更多信息,请参阅在Java中覆盖equals和hashCode 。

也许它类似于var1 == var2如何不等于快速,除非它们指向内存中的>相同的对象,而是你必须使用var1.equals(var2)

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

*更新:正如pst指出的那样,它还必须重新实现等于。

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

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

你必须覆盖CardhashCode()方法并使其返回相同的值,当且仅当卡片相等时 – 你也应该重写equals() 。 因为这是HashMap依赖的,以便找到键引用的对象; 就像现在一样,它是从Objectinheritance的那些方法的版本,只有当你使用相同的对象作为键时才会匹配,而你创建新的,虽然是“相等”的。