我用Java分析HashMap
源代码并得到关于put
方法的问题。
以下是JDK1.6中的put
方法:
public V put(K key, V value) {
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; 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;
}
我对if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
为什么这样的情况?
因为在Java超类Object
中,有hashCode
equals
和key.equals(k)
:
如果两个对象根据equals(Object)方法相等,则对两个对象中的每一个调用hashCode方法必须产生相同的整数结果。
因此key.hashCode() == k.hashCode()
暗示hash()
。
static int hash(int h) {
// This function ensures that hashCodes that differ only by
// constant multiples at each bit position have a bounded
// number of collisions (approximately 8 at default load factor).
h ^= (h >>> 20) ^ (h >>> 12);
return h ^ (h >>> 7) ^ (h >>> 4);
}
位于以下位置:
key.hashCode() == k.hashCode()
因此e.hash == hash
暗示if ((k = e.key) == key || key.equals(k))
。
那么为什么不是像 var clients = _clientService.GetClientSummary(true);
var results = context.Sites.AsNoTracking().OrderByDescending(s => s.Id).
Skip((pageIndex - 1) * pageSize).Take(pageSize);
result.Content = pageResult.Select(a => new QuoteSearch
{
Accepted = a.Accepted,
Created = a.Created,
Id = a.Id,
Customer = clients.Find(b => b.Id == a.ClientId).Name
}).ToList();
这样的条件?
答案 0 :(得分:8)
它只是一个优化:比较两个整数比调用equals()
更快。
如果两个哈希码不同,那么,根据equals
和hashCode
的约定,地图知道现有密钥不等于给定密钥,并且可以更快到下一个。
答案 1 :(得分:7)
它只是避免了方法调用:如果哈希(不是hashCode()
,它是地图自己的哈希)不同于条目的哈希值,知道它根本不必调用equals
。只是优化一点。
答案 2 :(得分:1)