0

我想知道在向 ? 中添加新元素(对象)之前检查了哪些因素(1、2 或 3?HashSet

如果 中存在唯一元素(对象) pre HashSet,并且我们尝试添加新对象,那么该集合是否仅比较哈希码或引用 usingequals()或两者?

  1. HashCode()
  2. equals()
  3. 1 和 2

换句话说,

如果hashTable.add(obj1) => returns true, 并且 hashTable.add(obj2) => returns false,

哪些因素被认为是检查obj2拒绝将其存储在HashSet.

我试图通过覆盖函数调用来打印日志,但是在将元素添加到集合时从未调用过 equals()。

  public class HashTest {
     int a,b;
     public HashTest(int a, int b){
     this.a=a;
     this.b=b;
   }
public static void main(String[]args){
    HashSet<HashTest> hashTable=new HashSet<HashTest>();
    HashTest obj1=new HashTest(1, 2);
    HashTest obj2=new HashTest(1, 2);
    System.out.println("1. obj1 hash code:"+obj1.hashCode());
    System.out.println("2. obj2 hash code:"+obj2.hashCode());
    System.out.println("inserting obj1 to the Hash Table:"+hashTable.add(obj1));
    System.out.println("inserting obj2 to the Hash Table:"+hashTable.add(obj2));
}
public boolean equals(Object obj){
    System.out.println("***equals called");
    return super.equals(obj);
}

public int hashCode(){
    System.out.println("***hashCode called");
    return super.hashCode();
}
  }

结果:

***hashCode 调用

  1. obj1 哈希码:4072869

***hashCode 调用

  1. obj2 哈希码:1671711

***hashCode 调用

将 obj1 插入哈希表:true

***hashCode 调用

将 obj2 插入哈希表:true

4

3 回答 3

1

两者都必须考虑。

考虑以下示例,

如果我们有一个HashSet<String>

我们添加Amy 和 May都是字符串对象,具有相同的 HashCode,但它们不相等

  1. hashCode 将确定要放入对象的存储桶。
  2. equals 将确定它们是否是同一个对象。

    希望有帮助。

于 2013-08-30T20:12:23.177 回答
1

两者都使用1。这就是哈希集(参见哈希表)的工作原理2

hashCode 首先确定使用的存储桶,然后equals始终用于最终的相等性测试。hashCode 和 equals 之间的规则解释了对象合约文档。

因此,如果失败(hashCode找到空存储桶)稍后equals失败(即存储桶中没有等效项),则该项目“不存在”并且可以添加。这也意味着hashCode测试可以“快速失败”但不能“快速成功”。


1身份相等 ( ==) 可以在等价 ( equals) 之前应用,因为它不会改变合同语义。但是,equals在所有集合类型(除了罕见的例外,如IdentityHashMap)中都使用它作为“最终”测试。

2有不同种类的哈希表;以上假设链接,但类似的推理适用于所有哈希策略。

于 2013-08-30T20:13:49.667 回答
1

AHashSet利用 a HashMap,如实现所示:

public boolean add(E e) {
    return map.put(e, PRESENT)==null;
}

map的实例在哪里HashMap。这里是实现HashMap#put(K, V)

public V put(K key, V value) {
    if (table == EMPTY_TABLE) {
        inflateTable(threshold);
    }
    if (key == null)
        return putForNullKey(value);
    int hash = hash(key);
    int i = indexFor(hash, table.length);
    @SuppressWarnings("unchecked")
    Entry<K,V> e = (Entry<K,V>)table[i];
    for(; e != null; e = e.next) {
        Object k;
        if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
            V oldValue = e.value;
            e.value = value;
            e.recordAccess(this);
            return oldValue;
        }
    }

    modCount++;
    addEntry(hash, key, value, i);
    return null;
}

我想你现在应该可以回答你自己的问题了。

于 2013-08-30T20:13:50.087 回答