Java 中的哈希键

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

在 java 中,当我使用字符串作为 Hashmap 的键时,得到的结果与使用字符串哈希码作为 HashMap 中的键时的结果略有不同。

有什么见解吗?

java hashmap hashtable string-hashing
6个回答
12
投票

当我使用字符串哈希码作为 HashMap 中的键时。

不能使用哈希码本身作为密钥。哈希码并不是唯一的 - 完全允许两个不相等的值具有相同的哈希码。您应该使用字符串 itself 作为键。然后,地图将首先比较哈希码(以快速缩小候选匹配范围),然后与

equals
比较真正字符串相等性。

当然,这是假设你的代码确实是你的问题所提出的,例如

HashMap<String, String> goodMap = new HashMap<String, String>();
goodMap.put("foo", "bar");

HashMap<Integer, String> badMap = new HashMap<Integer, String>();
badMap.put("foo".hashCode(), "bar");

如果您的代码确实是这样的,只需使用

HashMap<String, String>
即可。

来自

Object.hashCode()
的文档(强调我的):

hashCode 的通用约定是:

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

3
投票

当然。不同的字符串可以具有相同的 hashCode,因此如果您将两个这样的字符串作为键存储在映射中,您将有两个条目(因为字符串不同)。然而,如果您使用它们的 hashCode 作为键,您将只有一个条目(因为它们的 hashCode 是相同的)。

hashCode 不用于判断两个键是否相等。它仅用于为键分配存储桶。一旦找到桶,桶中包含的每个键都会与新键进行相等比较,如果找不到相等的键,则将键添加到桶中。


3
投票

问题是,即使两个对象不同,并不意味着它们的哈希码也不同。

两个不同的对象可以共享相同的哈希码。所以,你不应该将它们作为 HashMap 键。

此外,由于从

Object.hashCode()
方法返回的哈希码的类型为
int
,因此只能有
2^32
不同的值。这就是为什么对于不同的对象,根据哈希算法,您会发生“冲突”。

简而言之:-

!obj.equals(obj1)
并不能确保
obj.hashCode() != obj1.hashCode()


1
投票
对于同一个字符串,

HashCodes
可以相同或不同,所以要小心。也许这就是你得到不同结果的原因。

这是另一个SO问题。请参阅 Jon Skeet 接受的答案。


0
投票

仅当散列函数是完美散列时,您才能使用散列码作为密钥(参见例如GPERF)。只要您的关键对象不驻留在内存中,您就可以节省内存,这是正确的。


0
投票

巴尼奥德·德鲁斯·泰坦·巴克德·巴克德·克罗德姆巴尼德·巴克南姆·莫拉·吉奥德姆·科斯和巴克·巴克·巴克巴克马 巴克马 巴克马德·德·德·拉尔姆·托纳姆·奥纳姆·斯内斯·拉·纳德·拉克·巴德姆·阿加什阿尔巴尼亚 阿尔巴尼亚 阿尔巴尼亚 阿尔巴尼亚 阿尔巴尼亚 阿尔巴尼亚

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