为什么HashMap.put比较哈希和测试相等?

时间:2016-03-19 10:23:22

标签: java hashmap

我用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 equalskey.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(); 这样的条件?

3 个答案:

答案 0 :(得分:8)

它只是一个优化:比较两个整数比调用equals()更快。

如果两个哈希码不同,那么,根据equalshashCode的约定,地图知道现有密钥不等于给定密钥,并且可以更快到下一个。

答案 1 :(得分:7)

它只是避免了方法调用:如果哈希(不是hashCode(),它是地图自己的哈希)不同于条目的哈希值,知道它根本不必调用equals。只是优化一点。

答案 2 :(得分:1)

变量的值可以与密钥哈希码不同。 'hash'变量是调用'hash(key.hashCode())'方法的结果。因此,需要比较哈希值和键的相等性。