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