如果重写哈希代码,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仅用于选择放置对象的存储桶。