- 类型参数:
-
K
- 此映射维护的键的类型 -
V
- 映射值的类型
- 所有实现的接口:
-
Serializable
,Cloneable
,Map<K,
V>
Map
接口,当比较键(和值)时使用引用相等性代替对象相等性。换句话说,在IdentityHashMap
中,仅当(k1==k2)
时,两个键k1
和k2
被视为相等。(在普通的Map
实现(如HashMap
)中,仅当(k1==null ? k2==null : k1.equals(k2))
时,两个键k1
和k2
被视为相等。)
此类不是通用的Map
实现!虽然此类实现了Map
接口,但它故意违反了Map
的一般契约,该契约规定在比较对象时必须使用equals
方法。此类仅设计用于极少数需要引用相等性语义的情况。
此映射的视图集合对其元素也具有引用相等性语义。有关更多信息,请参阅keySet
、values
和entrySet
方法。
此类的典型用途是保持拓扑结构的对象图转换,例如序列化或深度复制。要执行这样的转换,程序必须维护一个“节点表”,以跟踪已处理的所有对象引用。即使发生相等情况,节点表也不能将不同的对象等同起来。此类的另一个典型用途是维护代理对象。例如,调试工具可能希望为正在调试的程序中的每个对象维护一个代理对象。
此类提供所有可选的映射操作,并允许null
值和null
键。此类不保证映射的顺序;特别是,它不保证顺序会随时间保持恒定。
此类对基本操作(get
和put
)提供恒定时间性能,假设系统标识哈希函数(System.identityHashCode(Object)
)在桶之间正确分散元素。
此类有一个调整参数(影响性能但不影响语义):预期最大大小。此参数是映射预计将保存的键-值映射的最大数量。在内部,此参数用于确定最初包含哈希表的桶数。预期最大大小和桶数之间的精确关系未指定。
如果映射的大小(键-值映射的数量)显着超过预期的最大大小,则增加桶数。增加桶数(“重新散列”)可能相当昂贵,因此最好创建具有足够大预期最大大小的标识哈希映射。另一方面,遍历集合视图所需的时间与哈希表中的桶数成正比,因此如果特别关注迭代性能或内存使用量,则最好不要将预期最大大小设置得太高。
请注意,此实现不是同步的。如果多个线程同时访问标识哈希映射,并且至少有一个线程在结构上修改了映射,则必须在外部同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅更改实例已包含的键关联的值不是结构修改。)通常通过在自然封装映射的某个对象上同步来实现此目的。如果不存在这样的对象,则应使用Collections.synchronizedMap
方法“包装”映射。最好在创建时执行此操作,以防止意外的非同步访问映射:
Map m = Collections.synchronizedMap(new IdentityHashMap(...));
由此类的所有“集合视图方法”返回的迭代器都是快速失败的:如果在创建迭代器后的任何时间内以任何方式结构上修改了映射,除了通过迭代器自身的remove
方法之外,迭代器将抛出ConcurrentModificationException
。因此,在面对并发修改时,迭代器会快速且干净地失败,而不是在未来的不确定时间面临任意的、非确定性的行为。
请注意,迭代器的快速失败行为无法保证,因为一般来说,在未同步的并发修改的情况下,不可能做出任何硬性保证。快速失败迭代器基于尽力而为的基础抛出ConcurrentModificationException
。因此,编写依赖此异常正确性的程序是错误的:快速失败迭代器仅用于检测错误。
此类是Java集合框架的成员。
- 实现注意事项:
-
这是一个简单的线性探测哈希表,例如在Sedgewick和Knuth的文本中描述。数组包含交替的键和值,偶数索引处是键,奇数索引处是值。(与使用单独数组相比,此安排对于大表具有更好的局部性。)对于许多Java实现和操作混合,此类将比使用链式而不是线性探测的
HashMap
提供更好的性能。 - 自:
- 1.4
- 参见:
-
Nested Class Summary
Nested classes/interfaces declared in class java.util.AbstractMap
AbstractMap.SimpleEntry<K,
V>, AbstractMap.SimpleImmutableEntry<K, V> -
Constructor Summary
ConstructorDescription构造一个新的、空的标识哈希映射,具有默认的预期最大大小(21)。IdentityHashMap
(int expectedMaxSize) 构造一个具有指定预期最大大小的新的、空映射。IdentityHashMap
(Map<? extends K, ? extends V> m) 构造一个包含指定映射中键-值映射的新的标识哈希映射。 -
Method Summary
Modifier and TypeMethodDescriptionvoid
clear()
从此映射中删除所有映射。clone()
返回此标识哈希映射的浅拷贝:键和值本身不会被克隆。boolean
containsKey
(Object key) 测试指定对象引用是否为此标识哈希映射中的键。boolean
containsValue
(Object value) 测试指定对象引用是否为此标识哈希映射中的值。entrySet()
返回此映射中包含的映射的Set
视图。boolean
将指定对象与此映射进行比较以判断是否相等。返回指定键映射到的值,如果此映射不包含该键的映射,则返回null
。int
hashCode()
返回此映射的哈希码值。boolean
isEmpty()
如果此标识哈希映射不包含键-值映射,则返回true
。keySet()
返回此映射中包含的键的基于标识的集合视图。在此标识哈希映射中将指定值与指定键关联。void
将指定映射中的所有映射复制到此映射中。如果存在此键的映射,则从此映射中删除该键的映射。boolean
仅当指定键当前映射到指定值时,才删除此键的条目。boolean
仅当指定键当前映射到指定值时,才替换此键的条目。int
size()
返回此标识哈希映射中键-值映射的数量。values()
返回此映射中包含的值的Collection
视图。Methods declared in class java.util.AbstractMap
toString
Methods declared in interface java.util.Map
compute, computeIfAbsent, computeIfPresent, forEach, getOrDefault, merge, putIfAbsent, replace, replaceAll
-
Constructor Details
-
IdentityHashMap
public IdentityHashMap()构造一个新的、空的标识哈希映射,具有默认的预期最大大小(21)。 -
IdentityHashMap
public IdentityHashMap(int expectedMaxSize) 构造一个具有指定预期最大大小的新的、空映射。将超出预期键-值映射数量放入映射可能导致内部数据结构增长,这可能会耗费一些时间。- 参数:
-
expectedMaxSize
- 映射的预期最大大小 - 抛出:
-
IllegalArgumentException
- 如果expectedMaxSize
为负
-
IdentityHashMap
构造一个包含指定映射中键-值映射的新的标识哈希映射。- 参数:
-
m
- 要放入此映射中的映射 - 抛出:
-
NullPointerException
- 如果指定映射为null
-
-
Method Details
-
size
public int size()返回此标识哈希映射中键-值映射的数量。 -
isEmpty
public boolean isEmpty()如果此标识哈希映射不包含键-值映射,则返回true
。 -
get
返回指定键所映射的值,如果此映射包含对于该键的映射,则返回null
。更正式地说,如果此映射包含从键
k
到值v
的映射,使得(key == k)
,则此方法返回v
;否则返回null
。(最多只能有一个这样的映射。)返回
null
值并不一定表示映射不包含该键;也可能是映射将该键明确映射到null
。可以使用containsKey
操作来区分这两种情况。 -
containsKey
测试指定对象引用是否为此身份哈希映射中的键。如果此映射包含具有键k
的映射,使得(key == k)
,则返回true
。- 指定者:
-
containsKey
在接口Map<K,
中V> - 覆盖:
-
containsKey
在类AbstractMap<K,
中V> - 参数:
-
key
- 可能的键 - 返回:
-
如果指定对象引用是此映射中的键,则返回
true
- 参见:
-
containsValue
测试指定对象引用是否为此身份哈希映射中的值。如果此映射包含具有值v
的映射,使得(value == v)
,则返回true
。- 指定者:
-
containsValue
在接口Map<K,
中V> - 覆盖:
-
containsValue
在类AbstractMap<K,
中V> - 参数:
-
value
- 要测试其在此映射中的存在性的值 - 返回:
-
如果此映射将一个或多个键映射到指定对象引用,则返回
true
- 参见:
-
put
在此身份哈希映射中将指定值与指定键关联。如果此映射已经包含
键的映射,则旧值将被替换,否则,将在此映射中插入新映射。 -
putAll
将指定映射中的所有映射复制到此映射中。对于指定映射中的每个映射,如果此映射已经包含
键的映射,则其值将替换为指定映射中的值;否则,将在此映射中插入新映射。- 指定者:
-
putAll
在接口Map<K,
中V> - 覆盖:
-
putAll
在类AbstractMap<K,
中V> - 参数:
-
m
- 要存储在此映射中的映射 - 抛出:
-
NullPointerException
- 如果指定映射为null
-
remove
如果存在,从此映射中移除此键的映射。仅当映射具有使得(key == k)
的键k
时,才会移除映射。 -
clear
public void clear()从此映射中移除所有映射。此调用返回后,映射将为空。 -
equals
比较指定的对象与此映射是否相等。如果给定对象也是一个映射,并且两个映射表示相同的对象引用映射,则返回true
。更正式地说,如果且仅当this.entrySet().equals(m.entrySet())
时,此映射等于另一个映射m
。请参阅entrySet
方法以获取此映射条目的相等规范。由于此映射基于引用相等性语义,如果将此映射与普通映射进行比较,则可能违反
Object.equals
合同的对称性和传递性要求。但是,Object.equals
合同在IdentityHashMap
实例之间是保证成立的。 -
hashCode
public int hashCode()返回此映射的哈希码值。映射的哈希码被定义为此映射的每个条目的哈希码之和。请参阅entrySet
方法以获取此映射条目的哈希码规范。此规范确保
m1.equals(m2)
意味着对于任何两个IdentityHashMap
实例m1
和m2
,m1.hashCode()==m2.hashCode()
,这是Object.hashCode()
的一般合同要求。由于此映射的
entrySet
方法返回的集合中的Map.Entry
实例基于引用相等性语义,如果正在比较的两个对象之一是IdentityHashMap
实例,另一个是普通映射,则可能违反前一段提到的Object.hashCode
的合同要求。 -
clone
返回此身份哈希映射的浅拷贝:键和值本身不会被克隆。- 覆盖:
-
clone
在类AbstractMap<K,
中V> - 返回:
- 此映射的浅拷贝
- 另请参见:
-
keySet
返回此映射中包含的键的基于身份的集合视图。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,通过Iterator.remove
、Set.remove
、removeAll
、retainAll
和clear
方法从映射中删除相应的映射。它不支持add
或addAll
方法。虽然此方法返回的对象实现了
Set
接口,但它不遵守Set
的一般合同。与其支持的映射一样,此方法返回的集合将元素相等性定义为引用相等性而不是对象相等性。这会影响其contains
、remove
、containsAll
、equals
和hashCode
方法的行为。返回的集合的
equals
方法仅在指定对象是包含与返回集合完全相同对象引用的集合时返回true
。如果通过此方法返回的集合与普通集合进行比较,则可能违反Object.equals
合同的对称性和传递性要求。但是,通过此方法返回的集合之间保证遵守Object.equals
合同。通过此方法返回的集合的
hashCode
方法返回集合中元素的身份哈希码之和,而不是它们的哈希码之和。这是为了强制执行equals
方法语义的更改,以便在通过此方法返回的集合之间强制执行Object.hashCode
方法的一般合同。 -
values
返回此映射中包含的值的Collection
视图。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,通过Iterator.remove
、Collection.remove
、removeAll
、retainAll
和clear
方法从映射中删除相应的映射。它不支持add
或addAll
方法。虽然此方法返回的对象实现了
Collection
接口,但它不遵守Collection
的一般合同。与其支持的映射一样,此方法返回的集合将元素相等性定义为引用相等性而不是对象相等性。这会影响其contains
、remove
和containsAll
方法的行为。 -
entrySet
返回此映射中包含的映射的Set
视图。返回集合中的每个元素都是基于引用相等性的Map.Entry
。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,可以通过Iterator.remove
、Set.remove
、removeAll
、retainAll
和clear
方法从映射中移除相应的映射。它不支持add
或addAll
方法。与支持映射相同,此方法返回的集合中的
Map.Entry
对象将键和值的相等性定义为引用相等性而不是对象相等性。这会影响这些Map.Entry
对象的equals
和hashCode
方法的行为。基于引用相等性的Map.Entry e
仅在o
是Map.Entry
且e.getKey()==o.getKey() && e.getValue()==o.getValue()
时才等于对象o
。为了适应这些相等性语义,hashCode
方法返回System.identityHashCode(e.getKey()) ^ System.identityHashCode(e.getValue())
。(虽然使用引用相等性比较键和值,但Map.Entry
对象本身不是。)由于此方法返回的集合中
Map.Entry
实例基于引用相等性的语义,如果将集合中的任何条目与普通映射条目进行比较,或者将此方法返回的集合与普通映射条目的集合进行比较(例如通过对普通映射调用此方法返回),可能会违反Object.equals(Object)
合同的对称性和传递性要求。但是,Object.equals
合同在基于标识的映射条目之间以及这些条目的集合之间是保证成立的。 -
remove
仅当指定的键当前映射到指定的值时,才删除该键的条目。更正式地说,如果此映射包含从键
k
到值v
的映射,使得(key == k)
和(value == v)
,则此方法将删除此键的映射并返回true
;否则返回false
。 -
replace
仅当指定的键当前映射到指定的值时,才替换该键的条目。更正式地说,如果此映射包含从键
k
到值v
的映射,使得(key == k)
和(oldValue == v)
,则此方法将将k
与newValue
关联并返回true
;否则返回false
。
-