我们是否必须重写放入哈希映射中的枚举的 equals/hashcode

问题描述 投票:0回答:2

我有一个枚举类,如下。

public enum Item {
   COKE("Coke", 25), PEPSI("Pepsi", 35), SODA("Soda", 45);
   private String name;
   private int price;

private Item(String name, int price) {
    this.name = name;
    this.price = price;
}

public String getName() {
    return name;
}

public long getPrice() {
    return price;
}
}

以及定义如下的哈希图

private Map<Item, Integer> inventory = new HashMap<Item, Integer>();

我是否需要重写枚举

Item
类中的 hashcode 和 equals 才能使
inventory.put()
inventory.get()
正常工作?如果没有,为什么?

java hash hashmap equals hashcode
2个回答
13
投票

不,你不知道。为什么?因为已经提供了这些方法的合理实现。

即使你想,你也做不到,因为这些方法是枚举中的

final

但是,不要将

HashMap
与枚举键类型一起使用:使用
EnumMap
,它专门用于枚举键,并且不使用
hashCode
equals
(它实际上使用
ordinal
)。


编辑:阅读完Enum.hashCode背后的原因是什么后,我注意到

hashCode
equals
的实现实际上是来自
Object
的实现。但这些合理的,因为枚举值的不可实例化。

如果您无法创建枚举值的新实例,则使用这些默认值没有问题:

  • 枚举值必须具有与其自身相同的哈希码值(并且该值是什么并不重要);
  • 枚举值必须等于其自身,而不是任何其他值,即身份相等。

0
投票

这篇文章是不久前写的,但我认为值得添加一些关于 enum hashCode() 的内容,这让我绊倒了......

枚举的 hashCode 在程序启动时是固定的,因为枚举本质上只是一个静态对象,因此 Object.hashCode() 将在程序运行期间返回相同的值。

但是,下次程序运行时,这很可能不是内存中的同一地址。

枚举是通过其在内存中的地址 (==) 进行比较(与 equals 进行比较),而不是通过 equals() 进行比较。这就是为什么 hashCode() 必须做同样的事情,或者正如文档所说的“类似的东西”(或多或少)。

如果您有其他包含枚举的类,并且您从 IDE 自动为其生成哈希码,则该新类的哈希码将取决于您运行代码的时间。如果这个其他类被持久化,它的哈希码在程序启动时将不相等。

如果您希望枚举哈希码始终保持不变,请对枚举的字符串进行哈希处理。这样,只有当有人更改枚举的字符串值时,它才会发生变化,并且还满足 Java 的 hashCode/equals() 契约要求。

© www.soinside.com 2019 - 2024. All rights reserved.