假设您有一个带有重写的equals,hashCode和clone方法的密钥类(KeyClass)。假设它有2个原始字段,一个String(名称)和一个int(id)。
现在你定义
KeyClass keyOriginal, keyCopy, keyClone;
keyOriginal = new KeyClass("original", 1);
keyCopy = new KeyClass("original", 1);
keyClone = KeyClass.clone();
现在
keyOriginal.hashCode() == keyCopy.hashCode() == keyClone.hashCode()
keyOriginal.equals(keyCopy) == true
keyCopy.equals(keyClone) == true
就HashMap而言,keyOriginal,keyCopy和keyClone是无法区分的。
现在,如果您使用keyOriginal将条目放入HashMap,则可以使用keyCopy或keyClone将其检索回来,即
map.put(keyOriginal, valueOriginal);
map.get(keyCopy) will return valueOriginal
map.get(keyClone) will return valueOriginal
此外,如果在将密钥放入地图后改变密钥,则无法检索原始值。所以对于例如
keyOriginal.name = "mutated";
keyOriginal.id = 1000;
Now map.get(keyOriginal) will return null
当你说map.keySet()时,它将返回地图中的所有键。 HashMap类如何知道地图中存储的键,值和条目的完整列表?
修改 据我了解,我认为它的工作原理是将Entry键作为最终变量。
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
(docjar.com/html/api/java/util/HashMap.java.html)。因此,即使我在将其放入地图后改变了密钥,也会保留原始密钥。我的理解是否正确?但即使保留原始密钥引用,仍然可以改变其内容。因此,如果内容发生变异,并且K,V仍然存储在原始位置,那么检索是如何工作的?
修改 如果在放入hashmap后改变密钥,则检索将失败。因此,不建议您使用可变的hashmap键。
答案 0 :(得分:9)
HashMap
维护一个条目表,其中包含根据哈希码组织的关联键和值的引用。如果改变键,则哈希码将改变,但HashMap
中的条目仍然根据原始哈希码放在哈希表中。这就是map.get(keyOriginal)
将返回null的原因。
map.keySet()
只是迭代哈希表,返回它所拥有的每个条目的密钥。
答案 1 :(得分:1)
如果您更改条目但不更改hashCode,则您是安全的。出于这个原因,最好的做法是在hashCode,equals和compareTo中创建所有字段,final
和不可变。
答案 2 :(得分:1)
简单地说,HashMap是计算机内存中包含键和值的对象。每个键都是唯一的(读取有关哈希码),每个键都指向一个值。
在您的代码示例中,每种情况下地图中出现的值都是相同的,因为键是相同的。当您更改密钥时,无法为其获取值,因为您从未使用变异的密钥向HashMap添加项目。
如果您添加了以下行:
map.put("mutated", 2);
在改变密钥之前,您将不再获得空值。