Module java.base
Package java.util

Class IdentityHashMap<K,V>

java.lang.Object
java.util.AbstractMap<K,V>
java.util.IdentityHashMap<K,V>
类型参数:
K - 此映射维护的键的类型
V - 映射值的类型
所有实现的接口:
Serializable, Cloneable, Map<K,V>

public class IdentityHashMap<K,V> extends AbstractMap<K,V> implements Map<K,V>, Serializable, Cloneable
此类使用哈希表实现Map接口,当比较键(和值)时使用引用相等性代替对象相等性。换句话说,在IdentityHashMap中,仅当(k1==k2)时,两个键k1k2被视为相等。(在普通的Map实现(如HashMap)中,仅当(k1==null ? k2==null : k1.equals(k2))时,两个键k1k2被视为相等。)

此类不是通用的Map实现!虽然此类实现了Map接口,但它故意违反了Map的一般契约,该契约规定在比较对象时必须使用equals方法。此类仅设计用于极少数需要引用相等性语义的情况。

此映射的视图集合对其元素也具有引用相等性语义。有关更多信息,请参阅keySetvaluesentrySet方法。

此类的典型用途是保持拓扑结构的对象图转换,例如序列化或深度复制。要执行这样的转换,程序必须维护一个“节点表”,以跟踪已处理的所有对象引用。即使发生相等情况,节点表也不能将不同的对象等同起来。此类的另一个典型用途是维护代理对象。例如,调试工具可能希望为正在调试的程序中的每个对象维护一个代理对象。

此类提供所有可选的映射操作,并允许null值和null键。此类不保证映射的顺序;特别是,它不保证顺序会随时间保持恒定。

此类对基本操作(getput)提供恒定时间性能,假设系统标识哈希函数(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>

    Nested classes/interfaces declared in interface java.util.Map

    Map.Entry<K,V>
  • Constructor Summary

    Constructors
    Constructor
    Description
    构造一个新的、空的标识哈希映射,具有默认的预期最大大小(21)。
    IdentityHashMap(int expectedMaxSize)
    构造一个具有指定预期最大大小的新的、空映射。
    IdentityHashMap(Map<? extends K,? extends V> m)
    构造一个包含指定映射中键-值映射的新的标识哈希映射。
  • Method Summary

    Modifier and Type
    Method
    Description
    void
    clear()
    从此映射中删除所有映射。
    clone()
    返回此标识哈希映射的浅拷贝:键和值本身不会被克隆。
    boolean
    测试指定对象引用是否为此标识哈希映射中的键。
    boolean
    测试指定对象引用是否为此标识哈希映射中的值。
    返回此映射中包含的映射的Set视图。
    boolean
    将指定对象与此映射进行比较以判断是否相等。
    V
    get(Object key)
    返回指定键映射到的值,如果此映射不包含该键的映射,则返回null
    int
    返回此映射的哈希码值。
    boolean
    如果此标识哈希映射不包含键-值映射,则返回true
    Set<K>
    keySet()
    返回此映射中包含的键的基于标识的集合视图。
    V
    put(K key, V value)
    在此标识哈希映射中将指定值与指定键关联。
    void
    putAll(Map<? extends K,? extends V> m)
    将指定映射中的所有映射复制到此映射中。
    V
    remove(Object key)
    如果存在此键的映射,则从此映射中删除该键的映射。
    boolean
    remove(Object key, Object value)
    仅当指定键当前映射到指定值时,才删除此键的条目。
    boolean
    replace(K key, V oldValue, V newValue)
    仅当指定键当前映射到指定值时,才替换此键的条目。
    int
    size()
    返回此标识哈希映射中键-值映射的数量。
    values()
    返回此映射中包含的值的Collection视图。

    Methods declared in class java.util.AbstractMap

    toString

    Methods declared in class java.lang.Object

    finalize, getClass, notify, notifyAll, wait, wait, wait
  • Constructor Details

    • IdentityHashMap

      public IdentityHashMap()
      构造一个新的、空的标识哈希映射,具有默认的预期最大大小(21)。
    • IdentityHashMap

      public IdentityHashMap(int expectedMaxSize)
      构造一个具有指定预期最大大小的新的、空映射。将超出预期键-值映射数量放入映射可能导致内部数据结构增长,这可能会耗费一些时间。
      参数:
      expectedMaxSize - 映射的预期最大大小
      抛出:
      IllegalArgumentException - 如果expectedMaxSize为负
    • IdentityHashMap

      public IdentityHashMap(Map<? extends K,? extends V> m)
      构造一个包含指定映射中键-值映射的新的标识哈希映射。
      参数:
      m - 要放入此映射中的映射
      抛出:
      NullPointerException - 如果指定映射为null
  • Method Details

    • size

      public int size()
      返回此标识哈希映射中键-值映射的数量。
      指定者:
      size 在接口 Map<K,V>
      覆盖:
      size 在类 AbstractMap<K,V>
      返回:
      此映射中键-值映射的数量
    • isEmpty

      public boolean isEmpty()
      如果此标识哈希映射不包含键-值映射,则返回true
      指定者:
      isEmpty 在接口 Map<K,V>
      覆盖:
      isEmpty 在类 AbstractMap<K,V>
      返回:
      如果此身份哈希映射不包含键-值映射,则返回true
    • get

      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
      参见:
    • containsKey

      public boolean containsKey(Object key)
      测试指定对象引用是否为此身份哈希映射中的键。如果此映射包含具有键k的映射,使得(key == k),则返回true
      指定者:
      containsKey 在接口 Map<K,V>
      覆盖:
      containsKey 在类 AbstractMap<K,V>
      参数:
      key - 可能的键
      返回:
      如果指定对象引用是此映射中的键,则返回true
      参见:
    • containsValue

      public boolean containsValue(Object value)
      测试指定对象引用是否为此身份哈希映射中的值。如果此映射包含具有值v的映射,使得(value == v),则返回true
      指定者:
      containsValue 在接口 Map<K,V>
      覆盖:
      containsValue 在类 AbstractMap<K,V>
      参数:
      value - 要测试其在此映射中的存在性的值
      返回:
      如果此映射将一个或多个键映射到指定对象引用,则返回true
      参见:
    • put

      public V put(K key, V value)
      在此身份哈希映射中将指定值与指定键关联。如果此映射已经包含键的映射,则旧值将被替换,否则,将在此映射中插入新映射。
      指定者:
      put 在接口 Map<K,V>
      覆盖:
      put 在类 AbstractMap<K,V>
      参数:
      key - 要与指定值关联的键
      value - 要与指定键关联的值
      返回:
      key关联的先前值,如果key之前没有映射,则返回null。(null返回还可能表示映射之前将nullkey关联。)
      参见:
    • putAll

      public void putAll(Map<? extends K,? extends V> m)
      将指定映射中的所有映射复制到此映射中。对于指定映射中的每个映射,如果此映射已经包含键的映射,则其值将替换为指定映射中的值;否则,将在此映射中插入新映射。
      指定者:
      putAll 在接口 Map<K,V>
      覆盖:
      putAll 在类 AbstractMap<K,V>
      参数:
      m - 要存储在此映射中的映射
      抛出:
      NullPointerException - 如果指定映射为null
    • remove

      public V remove(Object key)
      如果存在,从此映射中移除此键的映射。仅当映射具有使得(key == k)的键k时,才会移除映射。
      指定者:
      remove 在接口 Map<K,V>
      覆盖:
      remove 在类 AbstractMap<K,V>
      参数:
      key - 要从映射中移除的键
      返回:
      key关联的先前值,如果key之前没有映射,则返回null。(null返回还可能表示映射之前将nullkey关联。)
    • clear

      public void clear()
      从此映射中移除所有映射。此调用返回后,映射将为空。
      指定者:
      clear 在接口 Map<K,V>
      覆盖:
      clear 在类 AbstractMap<K,V>
    • equals

      public boolean equals(Object o)
      比较指定的对象与此映射是否相等。如果给定对象也是一个映射,并且两个映射表示相同的对象引用映射,则返回true。更正式地说,如果且仅当this.entrySet().equals(m.entrySet())时,此映射等于另一个映射m。请参阅entrySet方法以获取此映射条目的相等规范。

      由于此映射基于引用相等性语义,如果将此映射与普通映射进行比较,则可能违反Object.equals合同的对称性和传递性要求。但是,Object.equals合同在IdentityHashMap实例之间是保证成立的。

      指定者:
      equals 在接口 Map<K,V>
      覆盖:
      equals 在类 AbstractMap<K,V>
      参数:
      o - 与此映射进行比较的对象
      返回:
      如果指定对象等于此映射,则返回true
      另请参见:
    • hashCode

      public int hashCode()
      返回此映射的哈希码值。映射的哈希码被定义为此映射的每个条目的哈希码之和。请参阅entrySet方法以获取此映射条目的哈希码规范。

      此规范确保m1.equals(m2)意味着对于任何两个IdentityHashMap实例m1m2m1.hashCode()==m2.hashCode(),这是Object.hashCode()的一般合同要求。

      由于此映射的entrySet方法返回的集合中的Map.Entry实例基于引用相等性语义,如果正在比较的两个对象之一是IdentityHashMap实例,另一个是普通映射,则可能违反前一段提到的Object.hashCode的合同要求。

      指定者:
      hashCode 在接口 Map<K,V>
      覆盖:
      hashCode 在类 AbstractMap<K,V>
      返回:
      此映射的哈希码值
      另请参见:
    • clone

      public Object clone()
      返回此身份哈希映射的浅拷贝:键和值本身不会被克隆。
      覆盖:
      clone 在类 AbstractMap<K,V>
      返回:
      此映射的浅拷贝
      另请参见:
    • keySet

      public Set<K> keySet()
      返回此映射中包含的键的基于身份的集合视图。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,通过Iterator.removeSet.removeremoveAllretainAllclear方法从映射中删除相应的映射。它不支持addaddAll方法。

      虽然此方法返回的对象实现了Set接口,但它不遵守Set的一般合同。与其支持的映射一样,此方法返回的集合将元素相等性定义为引用相等性而不是对象相等性。这会影响其containsremovecontainsAllequalshashCode方法的行为。

      返回的集合的equals方法仅在指定对象是包含与返回集合完全相同对象引用的集合时返回true。如果通过此方法返回的集合与普通集合进行比较,则可能违反Object.equals合同的对称性和传递性要求。但是,通过此方法返回的集合之间保证遵守Object.equals合同。

      通过此方法返回的集合的hashCode方法返回集合中元素的身份哈希码之和,而不是它们的哈希码之和。这是为了强制执行equals方法语义的更改,以便在通过此方法返回的集合之间强制执行Object.hashCode方法的一般合同。

      指定者:
      keySet 在接口 Map<K,V>
      覆盖:
      keySet 在类 AbstractMap<K,V>
      返回:
      包含在此映射中的基于身份的键的集合视图
      另请参见:
    • values

      public Collection<V> values()
      返回此映射中包含的值的Collection视图。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,通过Iterator.removeCollection.removeremoveAllretainAllclear方法从映射中删除相应的映射。它不支持addaddAll方法。

      虽然此方法返回的对象实现了Collection接口,但它不遵守Collection的一般合同。与其支持的映射一样,此方法返回的集合将元素相等性定义为引用相等性而不是对象相等性。这会影响其containsremovecontainsAll方法的行为。

      指定者:
      values 在接口 Map<K,V>
      覆盖:
      values 在类 AbstractMap<K,V>
      返回:
      包含在此映射中的值的集合视图
    • entrySet

      public Set<Map.Entry<K,V>> entrySet()
      返回此映射中包含的映射的Set视图。返回集合中的每个元素都是基于引用相等性的Map.Entry。该集合由映射支持,因此对映射的更改会反映在集合中,反之亦然。如果在对集合进行迭代时修改了映射,则迭代的结果是未定义的。该集合支持元素移除,可以通过Iterator.removeSet.removeremoveAllretainAllclear方法从映射中移除相应的映射。它不支持addaddAll方法。

      与支持映射相同,此方法返回的集合中的Map.Entry对象将键和值的相等性定义为引用相等性而不是对象相等性。这会影响这些Map.Entry对象的equalshashCode方法的行为。基于引用相等性的Map.Entry e仅在oMap.Entrye.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合同在基于标识的映射条目之间以及这些条目的集合之间是保证成立的。

      指定者:
      entrySet 在接口 Map<K,V>
      返回:
      包含在此映射中的标识映射的集合视图
    • remove

      public boolean remove(Object key, Object value)
      仅当指定的键当前映射到指定的值时,才删除该键的条目。

      更正式地说,如果此映射包含从键k到值v的映射,使得(key == k)(value == v),则此方法将删除此键的映射并返回true;否则返回false

      指定者:
      remove 在接口 Map<K,V>
      参数:
      key - 与指定值关联的键
      value - 期望与指定键关联的值
      返回:
      如果值已被移除,则返回true
    • replace

      public boolean replace(K key, V oldValue, V newValue)
      仅当指定的键当前映射到指定的值时,才替换该键的条目。

      更正式地说,如果此映射包含从键k到值v的映射,使得(key == k)(oldValue == v),则此方法将将knewValue关联并返回true;否则返回false

      指定者:
      replace 在接口 Map<K,V>
      参数:
      key - 与指定值关联的键
      oldValue - 期望与指定键关联的值
      newValue - 要与指定键关联的值
      返回:
      如果值已被替换,则返回true