- java.lang.Object
-
- java.util.AbstractMap<K,V>
-
- java.util.IdentityHashMap<K,V>
-
- All Implemented Interfaces:
-
Serializable
,Cloneable
,Map<K,V>
public class IdentityHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Serializable, Cloneable
该类使用哈希表实现Map
接口,在比较键(和值)时使用引用相等代替对象相等。 换句话说,在IdentityHashMap
,当且仅当(k1==k2)
,两个键k1
和k2
被认为是相等的。 (正常情况下,Map
实现(如HashMap
)当两个键k1
和k2
被认为是相等的,如果且仅在(k1==null ? k2==null : k1.equals(k2))
)这个类不是通用的
Map
实现! 虽然这个类实现了Map
接口,但它有意违反了Map's
通用协议,当对比时,它要求使用equals
方法。 该类仅在需要引用相等语义的罕见情况下才能使用。此类的典型用法是拓扑保留对象图转换 ,如序列化或深层复制。 为了执行这种转换,程序必须保持跟踪已经处理的所有对象引用的“节点表”。 节点表不能等于不同的对象,即使它们恰好相等。 此类的另一个典型用途是维护代理对象 。 例如,调试工具可能希望为正在调试的程序中的每个对象维护代理对象。
此类提供所有可选的地图操作,并允许
null
值和null
键。 该类对地图的顺序不作任何保证; 特别是,它不能保证订单在一段时间内保持不变。假设系统标识散列函数(
System.identityHashCode(Object)
)正确地分散在这些存储桶中,这个类提供了基本操作(get
和put
)的恒定时间性能。该类有一个调整参数(其影响性能但不影响语义): 预期的最大大小 。 此参数是映射预期保存的键值映射的最大数量。 在内部,该参数用于确定最初包含散列表的桶数。 预期最大大小和桶数之间的精确关系未明确。
如果地图的大小(键值映射的数量)足够超过预期的最大大小,则桶的数量增加。 增加桶数(“rehashing”)可能相当昂贵,因此可以创建具有足够大的预期最大大小的身份哈希映射。 另一方面,集合视图的迭代需要时间与哈希表中的桶数成正比,因此如果您特别关注迭代性能或内存使用情况,则不会将预期的最大大小设置得太高。
请注意,此实现不同步。 如果多个线程同时访问身份哈希映射,并且至少一个线程在结构上修改映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅改变与实例已经包含的密钥相关联的值不是结构修改。)这通常通过对自然地封装映射的一些对象进行同步来实现。 如果没有这样的对象存在,应该使用
Collections.synchronizedMap
方法“包装”地图。 这最好在创建时完成,以防止意外的不同步访问地图:Map m = Collections.synchronizedMap(new IdentityHashMap(...));
由所有这个类的“集合视图方法”返回的集合的
iterator
方法返回的迭代器是故障快速的 :如果映射在迭代器创建之后的任何时间被结构化地修改,除了通过迭代器自己的remove
方法,迭代器会抛出一个ConcurrentModificationException
。 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。请注意,迭代器的故障快速行为无法保证,因为一般来说,在不同步并发修改的情况下,无法做出任何硬性保证。 失败快速的迭代器
ConcurrentModificationException
扔ConcurrentModificationException
。 因此,编写依赖于此异常的程序的正确性将是错误的: 故障快速迭代器应仅用于检测错误。实现说明:这是一个简单的线性探测哈希表,如Sedgewick和Knuth的文本中所述。 阵列交替保持键和值。 (与使用单独的数组相比,这对于大型表具有更好的局部性。)对于许多JRE实现和操作组合,此类将产生比
HashMap
更好的性能(使用链接而不是线性检测)。这个类是Java Collections Framework的成员。
- 从以下版本开始:
- 1.4
- 另请参见:
-
System.identityHashCode(Object)
,Object.hashCode()
,Collection
,Map
,HashMap
,TreeMap
, Serialized Form
-
-
Nested Class Summary
-
Nested classes/interfaces inherited from class java.util.AbstractMap
AbstractMap.SimpleEntry<K,V>, AbstractMap.SimpleImmutableEntry<K,V>
-
-
构造方法摘要
构造方法 Constructor 描述 IdentityHashMap()
构造一个带有默认预期最大大小的新的空标识哈希映射(21)。IdentityHashMap(int expectedMaxSize)
构造一个具有指定的预期最大大小的新的空白地图。IdentityHashMap(Map<? extends K,? extends V> m)
构造一个新的标识哈希映射,其中包含指定地图中的键值映射。
-
方法摘要
所有方法 接口方法 具体的方法 Modifier and Type 方法 描述 void
clear()
从这张地图中删除所有的映射。Object
clone()
返回此标识哈希映射的浅拷贝:键和值本身不被克隆。boolean
containsKey(Object key)
测试此标识哈希映射中指定的对象引用是否为密钥。boolean
containsValue(Object value)
测试指定的对象引用是否是此标识哈希映射中的值。Set<Map.Entry<K,V>>
entrySet()
返回此地图中包含的映射的Set
视图。boolean
equals(Object o)
将指定的对象与此映射进行比较以获得相等性。void
forEach(BiConsumer<? super K,? super V> action)
对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。V
get(Object key)
返回指定键映射到的值,如果此映射不包含键的映射,则返回null
。int
hashCode()
返回此地图的哈希码值。boolean
isEmpty()
如果此标识哈希映射不包含键值映射,则返回true
。Set<K>
keySet()
返回此地图中包含的键的基于身份的设置视图。V
put(K key, V value)
将指定的值与此标识哈希映射中的指定键相关联。void
putAll(Map<? extends K,? extends V> m)
将指定地图的所有映射复制到此地图。V
remove(Object key)
从该地图中删除此密钥的映射(如果存在)。void
replaceAll(BiFunction<? super K,? super V,? extends V> function)
将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。int
size()
返回此标识哈希映射中的键值映射的数量。Collection<V>
values()
返回此地图中包含的值的Collection
视图。-
Methods inherited from class java.util.AbstractMap
toString
-
-
-
-
构造方法详细信息
-
IdentityHashMap
public IdentityHashMap()
构造一个带有默认预期最大大小的新的空标识哈希映射(21)。
-
IdentityHashMap
public IdentityHashMap(int expectedMaxSize)
构造一个具有指定的预期最大大小的新的空白地图。 将超过预期数量的键值映射放入地图可能会导致内部数据结构增长,这可能会有些耗时。- 参数
-
expectedMaxSize
- 地图的预期最大大小 - 异常
-
IllegalArgumentException
- 如果expectedMaxSize
为负数
-
IdentityHashMap
public IdentityHashMap(Map<? extends K,? extends V> m)
构造一个新的标识哈希映射,其中包含指定地图中的键值映射。- 参数
-
m
- 其映射将被放置到该映射中的映射 - 异常
-
NullPointerException
- 如果指定的地图为空
-
-
方法详细信息
-
size
public int size()
返回此标识哈希映射中的键值映射的数量。
-
isEmpty
public boolean isEmpty()
如果此标识哈希映射不包含键值映射,则返回true
。
-
get
public V get(Object key)
返回指定键映射到的值,如果此映射不包含该键的映射,则返回null
。更正式地,如果该映射包含从键
k
到值v
的映射,使得(key == k)
,则该方法返回v
; 否则返回null
。 (最多可以有一个这样的映射。)返回值为
null
并不一定表示该映射不包含该键的映射; 地图也可能明确地将密钥映射到null
。 可以使用containsKey
操作来区分这两种情况。- Specified by:
-
get
在接口Map<K,V>
- 重写:
-
get
在AbstractMap<K,V>
- 参数
-
key
- 要返回其关联值的键 - 结果
-
指定键映射到的值,如果此映射不包含键的映射,
null
- 另请参见:
-
put(Object, Object)
-
containsKey
public boolean containsKey(Object key)
测试此标识哈希映射中指定的对象引用是否为密钥。- Specified by:
-
containsKey
在接口Map<K,V>
- 重写:
-
containsKey
中的AbstractMap<K,V>
- 参数
-
key
- 可能的键 - 结果
-
true
如果指定的对象引用是此映射中的键 - 另请参见:
-
containsValue(Object)
-
containsValue
public boolean containsValue(Object value)
测试指定的对象引用是否是此标识哈希映射中的值。- Specified by:
-
containsValue
在接口Map<K,V>
- 重写:
-
containsValue
在AbstractMap<K,V>
- 参数
-
value
- 要在此地图中存在的值要进行测试 - 结果
-
true
如果此映射将一个或多个键映射到指定的对象引用 - 另请参见:
-
containsKey(Object)
-
put
public V put(K key, V value)
将指定的值与此标识哈希映射中的指定键相关联。 如果地图先前包含了该键的映射,则替换旧值。- Specified by:
-
put
在接口Map<K,V>
- 重写:
-
put
在AbstractMap<K,V>
- 参数
-
key
- 指定值与之关联的关键字 -
value
- 与指定键相关联的值 - 结果
-
先前的值相关联
key
,或null
如果没有映射key
。 (Anull
返回也可以指示以前关联的地图null
与key
) - 另请参见:
-
Object.equals(Object)
,get(Object)
,containsKey(Object)
-
putAll
public void putAll(Map<? extends K,? extends V> m)
将指定地图的所有映射复制到此地图。 这些映射将替换此映射对当前在指定映射中的任何键的任何映射。- Specified by:
-
putAll
在接口Map<K,V>
- 重写:
-
putAll
在AbstractMap<K,V>
- 参数
-
m
- 要存储在此地图中的映射 - 异常
-
NullPointerException
- 如果指定的地图为空
-
clear
public void clear()
从这张地图中删除所有的映射。 此呼叫返回后,地图将为空。
-
equals
public boolean equals(Object o)
将指定的对象与此映射进行比较以获得相等性。 如果给定的对象也是一个地图,并且两个地图表示相同的对象引用映射,则返回true
。 更正式地,这张地图等于另一个地图m
如果且仅当this.entrySet().equals(m.entrySet())
。由于该映射的基于参考平等的语义,如果将该映射与法线映射进行比较,则可能会违反
Object.equals
合同的对称性和传递性要求。 但是,Object.equals
合约在IdentityHashMap
实例中IdentityHashMap
。- Specified by:
-
equals
在接口Map<K,V>
- 重写:
-
equals
在AbstractMap<K,V>
- 参数
-
o
- 要与此映射相等的对象进行比较 - 结果
-
true
如果指定的对象等于此映射 - 另请参见:
-
Object.equals(Object)
-
hashCode
public int hashCode()
返回此地图的哈希码值。 地图的哈希码被定义为地图entrySet()
视图中每个条目的哈希代码的总和。 这确保了m1.equals(m2)
意味着m1.hashCode()==m2.hashCode()
对于任何两个IdentityHashMap
实例m1
和m2
,所要求的一般合同Object.hashCode()
。由于该地图
entrySet
方法返回的集合中的Map.Entry
实例的基于参考平等的语义,如果被比较的两个对象之一是上一段中提到的Object.hashCode
的合同要求,则可能会被违反IdentityHashMap
实例,另一个是法线贴图。- Specified by:
-
hashCode
在接口Map<K,V>
- 重写:
-
hashCode
在AbstractMap<K,V>
- 结果
- 该地图的哈希码值
- 另请参见:
-
Object.equals(Object)
,equals(Object)
-
clone
public Object clone()
返回此标识哈希映射的浅拷贝:键和值本身不被克隆。- 重写:
-
clone
在AbstractMap<K,V>
- 结果
- 这张地图的浅拷贝
- 另请参见:
-
Cloneable
-
keySet
public Set<K> keySet()
返回此地图中包含的键的基于身份的设置视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改了映射,则迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove
,Set.remove
,removeAll
,retainAll
,和clear
方法。 它不支持add
或addAll
方法。当该方法返回的对象实现
Set
接口时, 不遵守Set's
通用合同。 像其背景图一样,该方法返回的集合将元素等式定义为引用相等而不是对象相等。 这会影响其行为contains
,remove
,containsAll
,equals
,并hashCode
方法。返回的集合的
equals
方法只有在指定的对象是包含与返回集完全相同的对象引用的集合时才返回true
。 如果将此方法返回的集合与正常集进行比较,则可能会违反Object.equals
合同的对称性和传递性要求。 但是,Object.equals
合同保证在此方法返回的集合中。返回的集合的
hashCode
方法返回集合中元素的身份哈希码的总和,而不是它们的哈希码的总和。 这是由equals
方法的语义变化规定的,以便通过此方法返回的集合中强制执行Object.hashCode
方法的一般合同。- Specified by:
-
keySet
在接口Map<K,V>
- 重写:
-
keySet
在AbstractMap<K,V>
- 结果
- 该地图中包含的键的基于身份的设置视图
- 另请参见:
-
Object.equals(Object)
,System.identityHashCode(Object)
-
values
public Collection<V> values()
返回此地图中包含的值的Collection
视图。 集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改了映射,则迭代的结果是未定义的。 该collection支持元素移除,即从映射中相应的映射,经由Iterator.remove
,Collection.remove
,removeAll
,retainAll
和clear
方法。 它不支持add
或addAll
方法。虽然此方法返回的对象实现了
Collection
接口,它不服从Collection's
总承包合同。 像其背景图一样,该方法返回的集合将元素等式定义为引用相等而不是对象相等。 这会影响其行为contains
,remove
和containsAll
方法。
-
entrySet
public Set<Map.Entry<K,V>> entrySet()
返回此地图中包含的映射的Set
视图。 返回的集合中的每个元素都是基于引用的基于平等的Map.Entry
。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改了映射,则迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.remove
,Set.remove
,removeAll
,retainAll
和clear
方法。 它不支持add
或addAll
方法。与支持映射一样,此方法返回的集合中的
Map.Entry
对象将键和值相等定义为引用相等而不是对象相等。 这会影响这些Map.Entry
对象的equals
和hashCode
方法的行为。 基于参考平等Map.Entry e
等于一个对象o
当且仅当o
是Map.Entry
和e.getKey()==o.getKey() && e.getValue()==o.getValue()
。 为了适应这些等价语义,hashCode
方法返回System.identityHashCode(e.getKey()) ^ System.identityHashCode(e.getValue())
。由于此方法返回的集合中的
Map.Entry
实例的基于参考平等的语义,如果将集合中的任何条目与正常条目进行比较,则可能会违反Object.equals(Object)
合同的对称性和传递性要求映射条目,或者如果将此方法返回的集合与一组法线贴图条目进行比较(例如通过在法线贴图上调用该方法将返回)。 但是,Object.equals
合同在基于身份的地图条目之间以及这些条目之间保留。
-
forEach
public void forEach(BiConsumer<? super K,? super V> action)
描述从接口Map
复制对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。 除非实现类另有指定,否则按照进入设置迭代的顺序执行操作(如果指定了迭代顺序)。操作引发的异常被转发给调用者。
-
replaceAll
public void replaceAll(BiFunction<? super K,? super V,? extends V> function)
描述从接口Map
复制将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。 函数抛出的异常被转发给调用方。- Specified by:
-
replaceAll
在接口Map<K,V>
- 参数
-
function
- 应用于每个条目的功能
-
-