Hashcode和Equals实现

时间:2018-04-24 08:58:02

标签: java hash hashmap

考虑以下HashMap<String,String> hashMap=new HashMap<>(); hashMap.put(new String("ABC"), "Hello"); hashMap.put("ABC", "Hello"); System.out.println(hashMap.size()); 实施

size

代码如何将StringBuffer作为1进行评估?但是,如果我使用String代替Category代码,则返回值为2。 这背后的原因是什么?

5 个答案:

答案 0 :(得分:6)

HashMap使用hashCode方法确定存储桶,然后使用equals来确定是否有任何现有对象与要添加的对象相同。在您的情况下,"ABC"new String("ABC")将具有相同的hashCode,并且String.equals将被视为相等。因此这两个对象将被视为相同。

如果您不想这样,那么您可以考虑使用IdentityHashMap使用对象引用来比较相等。

答案 1 :(得分:3)

HashMap使用Object.equals(other)作为2个对象是否应计为&#34;相同&#34;的最终仲裁者。使用String,equals可以有效地比较字符串的字符内容,因此"ABC".equals(new String("ABC"));将返回true

另一方面,

StringBuffer使用对象的equals默认实现,它基本上检查两个对象是引用相同的(即它们都指向了确切的相同的内存地址 - 这是==为java中的对象所做的事情。使用两个不同的new语句构造的两个StringBuffers永远不会是引用相同的,因此永远不会是equal。这有很好的理由:大部分时间,我们希望对象的equals方法为给定的参数返回相同的答案,无论它何时被调用。由于StringBuffer的内容可以被操作,因此两个缓冲区在一个时间点可能具有相同的内容,但是随后在其中一个缓冲区被附加到后面时具有不同的内容。

StringBuffer可变的事实可能使它成为用作地图键的不良候选者。除非您拥有与原始put完全相同的 StringBuffer,否则您将无法在地图上执行查找。相反,如果由于某种原因这种行为是你想要的,你可以使用IdentityHashMap,它将始终使用对象的内存地址来确定它是否相等到另一个,不管它的类型。注意使用带有字符串键的IdentityHashMap - 由于string interning,在代码中不同位置构造的2个等效字符串(来自文字)实际上指向同一块内存,因此参考相同。

答案 2 :(得分:0)

import matplotlib.pyplot as plt a=((open('A.txt').read()).lower()).split() c=((open('C.txt').read()).lower()).split() f=((open('F.txt').read()).lower()).split() documents=[a,f,c] import math names=[...] #important words for a in names: for b in names: count = 0 for x in documents: if a != b: if a in x and b in x: count += 1 else: n = x.count(a) if n >= 2: count += math.factorial(n)/math.factorial(n - 2)/2 print('{} x {} = {}'.format(a, b, count)) 中缺少类型。如果您想创建HashMap<String,String> hashMap=new HashMap<>();的地图,那么您将无法创建String, String个对象作为关键字。如果您想同时支持两者,则可以使用StringBuilder代替Object作为密钥。 如果您想支持StringString,那么您的代码将是

StringBuilder

以下是尺寸差异的解释。

&#34;任何价值&#34;被视为HashMap<Object,String> hashMap=new HashMap<Object, String>(); 类的实例。 StringStringBuilder不同。在您的代码中,同一个类的对象被创建为键,这会产生相同的hashCode(请参阅String中的hashCode()函数)。但是,String.java使用了Object.java中的StringBuilder。因此,他们有不同的hashCode,并进行相应的处理。

答案 3 :(得分:0)

HashMap的put(K key,V value)方法首先通过key.hashCode()%m散列到存储桶,然后遍历单个链接的Map.Entry对象列表以识别它 密钥通过key.equals(k)存在。如果找到一个键,它会更新该条目的值,否则它会将该键插入链表的前面

1)对于StringBuffer案例

    (i) new StringBuffer("ABC").equals(new StringBuffer("ABC")) is false
   (ii) new StringBuffer("ABC")!=new StringBuffer("ABC").hashCode() is false

这是因为StringBuffer不会覆盖并使用Objects equals(Object o)和hashCode()。 所以它们是地图中的两个不同的条目

2)对于字符串大小写

  (i) "ABC".equals(new String("ABC")) is true
 (ii) "ABC".hashCode()==new String("ABC").hashCode() is true

所以这两个是地图中的单个条目

答案 4 :(得分:0)

我认为你需要了解什么是hashmap, 等号和哈希码用于存储和检索分配的内存位置中的对象。 因此,在您的情况下,使用内容而不是keyObjects引用验证密钥,因为它是String。即使你创建String =“ABC”文字或新字符串(“ABC”); 在这种情况下,Equals方法结果为true,因此将现有密钥替换为新密钥。它是SET的基本概念。 HashMap使用SET作为键。因此,当我们尝试添加匹配的新密钥时,将使用equals方法替换现有密钥。 出于这个原因,我们应该正确地覆盖equals和hashcode方法。 规则: 如果两个对象相等,则它们必须具有相同的哈希码。 如果两个对象具有相同的哈希码,则它们可能相等也可能不相等。