【问题标题】:How value comparison is done in HashSet, HashMap, etcHashSet、HashMap等是如何进行值比较的
【发布时间】:2013-06-27 12:05:34
【问题描述】:

下面是我试过的一段代码;也给出了输出。

我的问题是:我在 HistoryTeardownDetails 的 setter 中为对象 htd1htd2 设置了相同的字符串值,因此在 Hashset 中应该只允许其中一个对象(如本例所示)的字符串实现)。

谁能帮助我了解如何使用哈希码的概念消除 Hashset 或任何集合中的重复项?

public class HashSetTry {
public static void main(String[]args){
HistoryTeardownDetails htd1=new HistoryTeardownDetails();
htd1.setProcess("ashwin");
HistoryTeardownDetails htd2=new HistoryTeardownDetails();
htd2.setProcess("ashwin");

HashSet<HistoryTeardownDetails> hashSet1=new HashSet<HistoryTeardownDetails>();
System.out.println("First --> "+hashSet1);

hashSet1.add(htd1);


System.out.println("Second --> "+hashSet1);

hashSet1.add(htd2);

System.out.println("Third --> "+hashSet1);

HashSet<String> hashSet2=new HashSet<String>();

System.out.println("First --> "+hashSet2);

hashSet2.add("abc");


System.out.println("Second --> "+hashSet2);

hashSet2.add("abc");

System.out.println("Third --> "+hashSet2);

HashSet<String> hashSet3=new HashSet<String>();

String abc=new String("sakthi");

System.out.println("First --> "+hashSet3);

hashSet3.add(abc);

String abcd=new String("sakthi");

System.out.println("Second --> "+hashSet3);

hashSet3.add(abcd);

System.out.println("Third --> "+hashSet3);

}
}

输出:

First --> []
Second --> [com.ford.wqr.object.HistoryTeardownDetails@20662066]
Third --> [com.ford.wqr.object.HistoryTeardownDetails@20662066,    com.ford.wqr.object.HistoryTeardownDetails@20862086]

First --> []
Second --> [abc]
Third --> [abc]

First --> []
Second --> [sakthi]
Third --> [sakthi]

【问题讨论】:

    标签: java collections hashcode hashset


    【解决方案1】:
    • HashSet 存储唯一元素。一个简单的规则

    如果您将相等的对象添加到哈希集中,则以前的对象将被新的对象替换。

    对于最后两种情况,您使用的是字符串,已经提供了equalshashcode 方法的实现。

    您需要为自己的类提供equalshashcode,然后添加到hashset 中。 然后只有它会给出所需的输出

    • 如果这两个对象被认为是equal,那么它们的哈希码必须相等

    我建议您为自己的类使用 eclipse 生成的 equalshashcode 方法。

    【讨论】:

      【解决方案2】:

      重复项由对象的equals 方法确定。

      您需要覆盖 HistoryTeardownDetails 类中的 equalshashCode 方法。

      【讨论】:

        【解决方案3】:

        HashSet.add 实际上是使用内部HashMap 的put 方法。那么让我们看看HashMap.put的源代码

        386     public V put(K key, V value) {
        387         if (key == null)
        388             return putForNullKey(value);
        389         int hash = hash(key.hashCode());
        390         int i = indexFor(hash, table.length);
        391         for (Entry<K,V> e = table[i]; e != null; e = e.next) {
        392             Object k;
        393             if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
        394                 V oldValue = e.value;
        395                 e.value = value;
        396                 e.recordAccess(this);
        397                 return oldValue;
        398             }
        399         }
        400 
        401         modCount++;
        402         addEntry(hash, key, value, i);
        403         return null;
        404     }
        

        在第 393 行看到,如果新键的哈希值等于任何成员的哈希值,那么它会检查键是否是相同的引用,并使用 equals 方法检查相等性。如果存在则返回而不添加

        【讨论】:

        • -1 用于转到代码而不是文档。文档是一种保证,应该优先于代码,代码只是一种实现。
        • @raptortech97...有趣的反对票..虽然我认为显示代码会更清楚地说明它
        【解决方案4】:

        我认为在 HashMaps 中相等是通过在 Object 中具有相同的 hashCode() 方法的哈希值来定义的。

        如果您提供 equals 实现,建议始终提供 hashCode 实现,以获得正确的 java.util.collection 行为。

        【讨论】:

          猜你喜欢
          • 2012-02-15
          • 2021-12-13
          • 1970-01-01
          • 2018-01-19
          • 2018-06-13
          • 1970-01-01
          • 2017-06-05
          • 2021-09-14
          • 1970-01-01
          相关资源
          最近更新 更多