我想知道在向HashSet
添加新元素(对象)之前检查了哪些因素(1,2或3?)?
如果HashSet
中预先存在唯一元素(对象),并且我们尝试添加新对象,那么集合是否只使用equals()
或两者来比较哈希码或引用?
HashCode()
equals()
换句话说,
如果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调用
*** hashCode调用
*** hashCode调用
将obj1插入哈希表:true
*** hashCode调用
将obj2插入哈希表:true
答案 0 :(得分:1)
必须考虑两者。
考虑以下示例,
如果我们有
HashSet<String>
我们添加 Amy和May 都是字符串对象,相同的HashCode ,但是 他们不相等。
equals将确定它们是否是同一个对象。
希望有所帮助。
答案 1 :(得分:1)
两者都使用 1 。这就是Hash-Set (see Hash table)的工作原理 2 。
hashCode
首先确定使用的存储区,然后equals
始终使用进行最终的相等性测试。 hashCode和equals之间的规则解释了Object契约文档。
因此,如果 hashCode
失败(即找到空桶)或,稍后,equals
将失败(即没有等效项目)在桶中),然后该项目“不存在”并且可以添加。这也意味着hashCode
测试可以“快速失败”,但不能“快速成功”。
1 可以在等价(==
)之前应用身份相等(equals
),因为它不会改变契约语义。但是,equals
在所有集合类型中使用(除IdentityHashMap
之类的罕见例外)作为“终极”测试。
2 有不同种类的哈希表;以上假设是链接,但类似的推理适用于所有哈希策略。
答案 2 :(得分:1)
HashSet
使用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;
}
我认为你现在应该能够回答你自己的问题了。