在HashMap中设置密钥类型,如何?

时间:2011-03-29 18:51:49

标签: java hashmap key

喜 我想创建一个HashMap(java)来存储Expression,这是我创建的一个小对象。 如何选择要使用的密钥类型?整数和字符串之间有什么区别?我想我只是不完全理解HashMap背后的想法,所以我不确定使用什么键。 谢谢!

4 个答案:

答案 0 :(得分:4)

Java HashMap依赖于两件事:

  • hashCode()方法,它返回一个从密钥生成并在地图中使用的整数
  • equals(..)方法,它应与计算的哈希值保持一致,这意味着如果两个键具有相同的哈希码,那么它们是相同的元素。

取自Java API doc的具体要求如下:

  • 每当在执行Java应用程序期间多次在同一对象上调用它时,hashCode方法必须始终返回相同的整数,前提是不修改对象的equals比较中使用的信息。从应用程序的一次执行到同一应用程序的另一次执行,此整数不需要保持一致。
  • 如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须生成相同的整数结果。
  • 如果两个对象根据equals(java.lang.Object)方法不相等,则不需要在两个对象中的每一个上调用hashCode方法必须生成不同的整数结果。但是,程序员应该知道为不等对象生成不同的整数结果可能会提高哈希表的性能。

如果您不提供任何类型的特定实现,则将对象的内存引用用作哈希码。这在大多数情况下通常都很好,但如果您有例如:

Expression e1 = new Expression(2,4,PLUS);
Expression e2 = new Expression(2,4,PLUS);

(我实际上并不知道你需要在你的hashmap中放置什么,所以我只是在猜测)

然后,由于它们是两个不同的对象,尽管具有相同的参数,它们将具有不同的哈希码。对于您的具体情况,这可能是或不是问题。

如果它不仅仅是在不关心这些细节的情况下使用hasmap,那么你需要提供一种更好的方法来计算你的Expression类的哈希码和相等性。

您可以以递归方式(通过计算子代码的哈希码计算哈希码)或以天真的方式(可能通过toString()表示计算哈希码)。

最后,如果你打算只使用简单的类型作为键(就像你说的整数或字符串),不要担心,没有区别。在这两种情况下,两个不同的项将具有相同的哈希码。一些例子:

assert(new String("hello").hashCode() == new String("hello").hashCode());
int x = 123;
assert(new Integer(x).hashCode() == new Integer(123).hashCode());

请注意,带字符串的示例通常不正确,就像我之前解释过的那样,这只是因为字符串的hashcode方法根据字符串本身的内容计算值。

答案 1 :(得分:1)

关键是您用来识别对象的方法。您可能希望根据名称识别数字。

Map<String,Integer> numbersByName = new HashMap<String,Integer>();

numbersByName.put("one",Integer.valueOf(1));
numbersByName.put("two",Integer.valueOf(2));
numbersByName.put("three",Integer.valueOf(3));
... etc

然后你可以通过

来解决它们
Integer three = numbersByName.get("three");

或者你可能需要走另一条路。如果您知道您将拥有整数值,并且想要名称,则可以将整数映射到字符串

Map<String,Integer> numbersByValue = new HashMap<String,Integer>();

numbersByValue.put(Integer.valueOf(1),"one");
numbersByValue.put(Integer.valueOf(2),"two");
numbersByValue.put(Integer.valueOf(3),"three");
... etc

然后把它拿出来

String three = numbersByValue.get(Integer.valueOf(3));

答案 2 :(得分:0)

键及其关联值都是对象。当您从HashMap中获取某些内容时,必须将其强制转换为它所代表的实际对象类型(我们可以这样做,因为Java中的所有对象都继承了Object类)。因此,如果您的键是字符串并且您的值是整数,那么您将执行以下操作:

Integer myValue = (Integer)myMap.get("myKey");

但是,您可以使用Java泛型来告诉编译器您将只使用字符串和整数:

HashMap<String,Integer> myMap = new HashMap<String,Integer>();

有关HashMap的详细信息,请参阅http://download.oracle.com/javase/1.4.2/docs/api/java/util/HashMap.html

答案 3 :(得分:0)

如果您不想查找表达式,为什么要将它们存储在地图中? 但是如果你愿意,那么关键是你用来查找的项目。