我正在尝试创建一个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;
}
}
答案 0 :(得分:12)
班级(Card
)错过了equals(Object)
和hashCode()
的正确实施
如果没有这两个定义,将无法正常工作。 (它编译得很好,因为这些方法都是虚拟的,并且在所有对象中都是继承的,因为它们是Object的一部分:HashMap在编译时不能强制执行此操作。)请参阅上面的链接以获取所需的合同。
这两个方法都需要实现,因为hashCode
确定HashMap实现中使用的哈希桶,equals
是确保对象是值等于(多个对象可以具有相同hashCode
,这也是equals
也需要的原因。有关更多常规哈希详细信息,请参阅Hash table。
如果这些方法没有重载,则使用Object中定义的实现。也就是说,x.equals(y)
具有接近 - x == y
语义,hashCode
每个合约返回一个稳定数字。这有效地使地图像身份地图一样工作(当Card对象是键时):只有完全相同的对象可以检索以前存储的值 - 每个其他获取将返回如所观察到的那样。
快乐的编码。
答案 1 :(得分:3)
确实正是因为这个问题。
您需要定义卡片上的平等含义,因此您需要覆盖equals
和hashCode
方法。
如果不这样做,则假设两张牌只有相同的实例才相等。 (与equals
的默认行为一样。)
请注意,覆盖equals
和hashCode
都非常重要,因为两个等于的对象必须哈希到{{1}的相同值正常工作。
有关详细信息,请参阅Overriding equals and hashCode in Java。
答案 2 :(得分:2)
也许它类似于var1 == var2如何不等于它们,除非它们指向&gt;内存中的相同对象,而不是必须使用var1.equals(var2)
几乎。正如您所料,哈希映射需要一种获取对象哈希码的方法。在Java中,这是由hashCode method提供的,它由Object实现,但需要被Card类覆盖。
*更新:正如pst指出的那样,它还必须重新实现等于。
答案 3 :(得分:1)
您需要实现hashCode和equals方法,因为这允许在两个不同的对象上进行相等性测试,并且还有助于哈希映射存储。如果不实现这些,即使它们的属性相同,也会看到两个对象是不同的。有关详细信息,请参阅http://www.jchq.net/certkey/0902certkey.htm。
答案 4 :(得分:1)
卡片应覆盖equals
和hashCode
。
看看这里:http://www.ibm.com/developerworks/java/library/j-jtp05273/index.html
答案 5 :(得分:1)
您必须覆盖hashCode()
的{{1}}方法,并且当且仅当卡片相同时才返回相同的值 - 您也应该覆盖Card
。因为这是equals()
依赖的内容,以便找到键引用的对象;就像现在一样,它是从HashMap
继承的那些方法的版本正在被使用,只有当你使用相同的对象作为键时才会匹配,而你正在创建新的,尽管是“相等”的。