为什么要遍历一个具有乘法值的存储桶,一次调用hashCode()?

问题描述 投票:1回答:5

我有一个以下课程

public class Animal {

    private int hash;

    public Animal(int hash) {
        this.hash = hash;
    }

    @Override
    public int hashCode() {
        System.out.println(hash);
        return hash;
    }
}

和此代码

    public static void main(String[] args) {
        Map<Animal, Integer> map = new HashMap<>();
        for (int i = 0; i < 4; i++) {
            map.put(new Animal(16 * i), i);
        }

        Animal an = new Animal(16*4);
        map.put(an, 1);

        for (int i = 5; i < 9; i++) {
            map.put(new Animal(16 * i), i);
        }
        Integer value = map.get(an);
    }

据我了解,所有这些值都应放在一个存储桶中(由于其哈希码)。在最后一次调用map.get(an)时,hashCode()仅被调用一次(根据控制台),但是在通过存储桶进行迭代并使用正确的hashCode()查找条目时,不应多次调用hashCode()吗?

我有一个以下类,公共类Animal {private int hash; public Animal(int hash){this.hash = hash; } @Override public int hashCode(){System.out ....

java equals hashcode
5个回答
3
投票

单个存储桶可能包含具有不同hashCode的键,并且将相关存储桶的键hashCode与您要添加/搜索的键进行比较。但是,hashCode缓存在Map.Entry中,因此无需为hashCode中已经存在的Entry调用键的Map方法:

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    V value;
    Node<K,V> next;

    Node(int hash, K key, V value, Node<K,V> next) {
        this.hash = hash; // here the hash code is cached
        this.key = key;
        this.value = value;
        this.next = next;
    }
    ...
}

2
投票

否,哈希码用于查找存储桶,这需要对hashcode的单个调用(在map.get(an)的参数上调用)。


0
投票

最多您可以期望hashCode()被完全调用。调用次数是HashMap的实现详细信息,您不应期望任何特定行为,也不应观察到行为是稳定的。由于hashCode()可以以不同的方式实现,甚至成本很高,因此仅调用一次是一个合理的选择,即使需要多次调用,也要使用返回值代替对hashCode()的新调用。但是,这仅是一种猜测,因此不应假定。


0
投票

每个人都已经回答了问题。我想从HashMap捕获代码以提供更多信息


0
投票

确定存储桶后,HashMap将使用。eqauls确定与提供的对象匹配的链表节点。查看实现:

© www.soinside.com 2019 - 2024. All rights reserved.