哈希集与“桶”一起使用。它根据它们的哈希码将值存储在这些“桶”中。使用该方法,“桶”中可以有多个成员,具体取决于这些成员是否相等equals(Object)
。
因此,假设我们构造了一个包含 10 个桶的哈希集,为了参数,并将整数 1、2、3、5、7、11 和 13 添加到其中。int 的哈希码就是 int。我们最终会得到这样的结果:
- (空的)
- 1, 11
- 2
- 3、13
- (空的)
- 5
- (空的)
- 7
- (空的)
- (空的)
使用集合的传统方法是查看成员是否在该集合中。所以当我们说,“这组里有 11 个吗?” 哈希集将 11 乘以 10 取模,得到 1,然后查看第二个存储桶(当然,我们的存储桶是从 0 开始的)。
这使得查看成员是否属于集合变得非常非常快。如果我们添加另一个11,哈希集会查看它是否已经存在。如果有就不会再添加了。它使用该equals(Object)
方法来确定,当然,11 等于 11。
像“abc”这样的字符串的哈希码取决于该字符串中的字符。当添加重复字符串“abc”时,哈希集会在正确的桶中查找,然后使用该equals(Object)
方法查看该成员是否已经存在。字符串的equals(Object)
方法也取决于字符,所以“abc”等于“abc”。
但是,当您使用 StringBuffer 时,每个 StringBuffer 都有一个基于其对象 ID 的哈希码和相等性。它不会覆盖基本equals(Object)
和hashCode()
方法,因此每个 StringBuffer 都将哈希集视为不同的对象。它们实际上并不是重复的。
当您将 StringBuffers 打印到输出时,您正在调用 StringBuffers 上的 toString() 方法。这使它们看起来像重复的字符串,这就是您看到该输出的原因。
这也是为什么hashCode()
在你 override时覆盖非常重要的原因equals(Object)
,否则 Set 会在错误的存储桶中查找,你会得到一些非常奇怪和不可预测的行为!