如果重写哈希代码,Hashmap键如何表现,只返回一个常数?
我有一个关于Java Hashmap
的小问题。 如果我覆盖hashCode
方法,使得:
@Override public int hashCode(){ return 9; }
这将导致所有HashMap
键具有相同的索引。 它们是否会被放置在地图中的链表结构中,还是地图只包含替换所有其他键的最后一个键?
它们将被放置在地图中的链表结构中,假设您没有覆盖equals
方法以始终返回true。 不同的键可能具有相同的hashCode,但如果所有键具有相同的hashCode,则您的HashMap将成为链接列表,这首先会破坏使用此结构的目的。
您可以在HashMap
实现中亲自查看:
/** * Associates the specified value with the specified key in this map. * If the map previously contained a mapping for the key, the old * value is replaced. * * @param key key with which the specified value is to be associated * @param value value to be associated with the specified key * @return the previous value associated with key, or * null if there was no mapping for key. * (A null return can also indicate that the map * previously associated null with key.) */ public V put(K key, V value) { if (key == null) return putForNullKey(value); int hash = hash(key.hashCode()); // hash would always be the same if hashCode is constant int i = indexFor(hash, table.length); // i would always be the same if hashCode is constant for (Entry e = table[i]; e != null; e = e.next) { Object k; if (e.hash == hash && ((k = e.key) == key || key.equals(k))) { // the key is searched using the // equals method V oldValue = e.value; e.value = value; e.recordAccess(this); return oldValue; } } modCount++; addEntry(hash, key, value, i); return null; }
哈希码值用于减少对象的搜索时间。 哈希码值对于不同的对象不一定是唯一的。 实际上,hashCode()方法可以以这样的方式被覆盖,即它为所有对象返回一个常量整数(但这会破坏hashCode()方法的目的)。 但是,类Object的默认实现确实为每个对象返回一个唯一的整数,因为它将对象的内部地址映射为整数并返回相同的整数。 但这不是必需的
它是否显示为链表是有争议的,因为它没有在文档中说明。 但是,它肯定会保留所有项目的唯一键(即返回true
键为equals
方法)。
class Nine { final String value; public Nine(String value) { this.value = value; } @Override public int hashCode() { return 9; } @Override public boolean equals(Object it) { return it instanceof Nine && ((Nine) it).value.equals(value); } @Override public String toString() { return value; } } class AlwaysNine extends Nine { public AlwaysNine(String value) { super(value); } @Override public boolean equals(Object it) { return it instanceof Nine; } } public void test() { System.out.println("Hello"); Map testMap = new HashMap(); testMap.put(new Nine("Nine"), "Nine"); testMap.put(new Nine("nine"), "nine"); testMap.put(new AlwaysNine("nIne"), "nIne"); System.out.println(testMap); }
版画
{Nine=nIne, nine=nine}
这certificate只有重写equals
会强制键看起来是相同的…正如预期的那样,因为hashCode
仅用于选择放置对象的存储桶。