Module  java.base
软件包  java.util

Class IdentityHashMap<K,V>

  • All Implemented Interfaces:
    SerializableCloneableMap<K,V>


    public class IdentityHashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Serializable, Cloneable
    该类使用哈希表实现Map接口,在比较键(和值)时使用引用相等代替对象相等。 换句话说,在IdentityHashMap ,当且仅当(k1==k2) ,两个键k1k2被认为是相等的。 (正常情况下, Map实现(如HashMap )当两个键k1k2被认为是相等的,如果且仅在(k1==null ? k2==null : k1.equals(k2))

    这个类不是通用的Map实现! 虽然这个类实现了Map接口,但它有意违反了Map's通用协议,当对比时,它要求使用equals方法。 该类仅在需要引用相等语义的罕见情况下才能使用。

    此类的典型用法是拓扑保留对象图转换 ,如序列化或深层复制。 为了执行这种转换,程序必须保持跟踪已经处理的所有对象引用的“节点表”。 节点表不能等于不同的对象,即使它们恰好相等。 此类的另一个典型用途是维护代理对象 例如,调试工具可能希望为正在调试的程序中的每个对象维护代理对象。

    此类提供所有可选的地图操作,并允许null值和null键。 该类对地图的顺序不作任何保证; 特别是,它不能保证订单在一段时间内保持不变。

    假设系统标识散列函数( System.identityHashCode(Object) )正确地分散在这些存储桶中,这个类提供了基本操作( getput )的恒定时间性能。

    该类有一个调整参数(其影响性能但不影响语义): 预期的最大大小 此参数是映射预期保存的键值映射的最大数量。 在内部,该参数用于确定最初包含散列表的桶数。 预期最大大小和桶数之间的精确关系未明确。

    如果地图的大小(键值映射的数量)足够超过预期的最大大小,则桶的数量增加。 增加桶数(“rehashing”)可能相当昂贵,因此可以创建具有足够大的预期最大大小的身份哈希映射。 另一方面,集合视图的迭代需要时间与哈希表中的桶数成正比,因此如果您特别关注迭代性能或内存使用情况,则不会将预期的最大大小设置得太高。

    请注意,此实现不同步。 如果多个线程同时访问身份哈希映射,并且至少一个线程在结构上修改映射,则必须在外部进行同步。 (结构修改是添加或删除一个或多个映射的任何操作;仅改变与实例已经包含的密钥相关联的值不是结构修改。)这通常通过对自然地封装映射的一些对象进行同步来实现。 如果没有这样的对象存在,应该使用Collections.synchronizedMap方法“包装”地图。 这最好在创建时完成,以防止意外的不同步访问地图:

      Map m = Collections.synchronizedMap(new IdentityHashMap(...)); 

    由所有这个类的“集合视图方法”返回的集合的iterator方法返回的迭代器是故障快速的 :如果映射在迭代器创建之后的任何时间被结构化地修改,除了通过迭代器自己的remove方法,迭代器会抛出一个ConcurrentModificationException 因此,面对并发修改,迭代器将快速而干净地失败,而不是在未来未确定的时间冒着任意的非确定性行为。

    请注意,迭代器的故障快速行为无法保证,因为一般来说,在不同步并发修改的情况下,无法做出任何硬性保证。 失败快速的迭代器ConcurrentModificationExceptionConcurrentModificationException 因此,编写依赖于此异常的程序的正确性将是错误的: 故障快速迭代器应仅用于检测错误。

    实现说明:这是一个简单的线性探测哈希表,如Sedgewick和Knuth的文本中所述。 阵列交替保持键和值。 (与使用单独的数组相比,这对于大型表具有更好的局部性。)对于许多JRE实现和操作组合,此类将产生比HashMap更好的性能(使用链接而不是线性检测)。

    这个类是Java Collections Framework的成员。

    从以下版本开始:
    1.4
    另请参见:
    System.identityHashCode(Object)Object.hashCode()CollectionMapHashMapTreeMapSerialized Form
    • 构造方法详细信息

      • 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​()
        返回此标识哈希映射中的键值映射的数量。
        Specified by:
        size在接口 Map<K,V>
        重写:
        sizeAbstractMap<K,V>
        结果
        该地图中键值映射的数量
      • isEmpty

        public boolean isEmpty​()
        如果此标识哈希映射不包含键值映射,则返回 true
        Specified by:
        isEmpty在接口 Map<K,V>
        重写:
        isEmptyAbstractMap<K,V>
        结果
        true如果此标识哈希映射不包含键值映射
      • get

        public V get​(Object key)
        返回指定键映射到的值,如果此映射不包含该键的映射,则返回null

        更正式地,如果该映射包含从键k到值v的映射,使得(key == k) ,则该方法返回v ; 否则返回null (最多可以有一个这样的映射。)

        返回值为null并不一定表示该映射不包含该键的映射; 地图也可能明确地将密钥映射到null 可以使用containsKey操作来区分这两种情况。

        Specified by:
        get在接口 Map<K,V>
        重写:
        getAbstractMap<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>
        重写:
        containsValueAbstractMap<K,V>
        参数
        value - 要在此地图中存在的值要进行测试
        结果
        true如果此映射将一个或多个键映射到指定的对象引用
        另请参见:
        containsKey(Object)
      • put

        public V put​(K key,
                     V value)
        将指定的值与此标识哈希映射中的指定键相关联。 如果地图先前包含了该键的映射,则替换旧值。
        Specified by:
        put在接口 Map<K,V>
        重写:
        putAbstractMap<K,V>
        参数
        key - 指定值与之关联的关键字
        value - 与指定键相关联的值
        结果
        先前的值相关联key ,或null如果没有映射key (A null返回也可以指示以前关联的地图nullkey
        另请参见:
        Object.equals(Object)get(Object)containsKey(Object)
      • putAll

        public void putAll​(Map<? extends K,? extends V> m)
        将指定地图的所有映射复制到此地图。 这些映射将替换此映射对当前在指定映射中的任何键的任何映射。
        Specified by:
        putAll在接口 Map<K,V>
        重写:
        putAllAbstractMap<K,V>
        参数
        m - 要存储在此地图中的映射
        异常
        NullPointerException - 如果指定的地图为空
      • remove

        public V remove​(Object key)
        从该地图中删除此密钥的映射(如果存在)。
        Specified by:
        remove在接口 Map<K,V>
        重写:
        removeAbstractMap<K,V>
        参数
        key - 要从地图中删除其映射的密钥
        结果
        先前的值相关联key ,或null如果没有映射key (A null返回也可以指示以前关联的地图nullkey
      • clear

        public void clear​()
        从这张地图中删除所有的映射。 此呼叫返回后,地图将为空。
        Specified by:
        clear在接口 Map<K,V>
        重写:
        clearAbstractMap<K,V>
      • 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>
        重写:
        equalsAbstractMap<K,V>
        参数
        o - 要与此映射相等的对象进行比较
        结果
        true如果指定的对象等于此映射
        另请参见:
        Object.equals(Object)
      • hashCode

        public int hashCode​()
        返回此地图的哈希码值。 地图的哈希码被定义为地图entrySet()视图中每个条目的哈希代码的总和。 这确保了m1.equals(m2)意味着m1.hashCode()==m2.hashCode()对于任何两个IdentityHashMap实例m1m2 ,所要求的一般合同Object.hashCode()

        由于该地图entrySet方法返回的集合中的Map.Entry实例的基于参考平等的语义,如果被比较的两个对象之一是上一段中提到的Object.hashCode的合同要求,则可能会被违反IdentityHashMap实例,另一个是法线贴图。

        Specified by:
        hashCode在接口 Map<K,V>
        重写:
        hashCodeAbstractMap<K,V>
        结果
        该地图的哈希码值
        另请参见:
        Object.equals(Object)equals(Object)
      • clone

        public Object clone​()
        返回此标识哈希映射的浅拷贝:键和值本身不被克隆。
        重写:
        cloneAbstractMap<K,V>
        结果
        这张地图的浅拷贝
        另请参见:
        Cloneable
      • keySet

        public Set<K> keySet​()
        返回此地图中包含的键的基于身份的设置视图。 该集合由地图支持,因此对地图的更改将反映在集合中,反之亦然。 如果在集合中的迭代正在进行时修改了映射,则迭代的结果是未定义的。 该组支持元件移除,即从映射中相应的映射,经由Iterator.removeSet.removeremoveAllretainAll ,和clear方法。 它不支持addaddAll方法。

        当该方法返回的对象实现Set接口时, 遵守Set's通用合同。 像其背景图一样,该方法返回的集合将元素等式定义为引用相等而不是对象相等。 这会影响其行为containsremovecontainsAllequals ,并hashCode方法。

        返回的集合的equals方法只有在指定的对象是包含与返回集完全相同的对象引用的集合时才返回true 如果将此方法返回的集合与正常集进行比较,则可能会违反Object.equals合同的对称性和传递性要求。 但是, Object.equals合同保证在此方法返回的集合中。

        返回的集合的hashCode方法返回集合中元素的身份哈希码的总和,而不是它们的哈希码的总和。 这是由equals方法的语义变化规定的,以便通过此方法返回的集合中强制执行Object.hashCode方法的一般合同。

        Specified by:
        keySet在接口 Map<K,V>
        重写:
        keySetAbstractMap<K,V>
        结果
        该地图中包含的键的基于身份的设置视图
        另请参见:
        Object.equals(Object)System.identityHashCode(Object)
      • values

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

        虽然此方法返回的对象实现了Collection接口,它服从Collection's总承包合同。 像其背景图一样,该方法返回的集合将元素等式定义为引用相等而不是对象相等。 这会影响其行为containsremovecontainsAll方法。

        Specified by:
        values在接口 Map<K,V>
        重写:
        valuesAbstractMap<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等于一个对象o当且仅当oMap.Entrye.getKey()==o.getKey() && e.getValue()==o.getValue() 为了适应这些等价语义, hashCode方法返回System.identityHashCode(e.getKey()) ^ System.identityHashCode(e.getValue())

        由于此方法返回的集合中的Map.Entry实例的基于参考平等的语义,如果将集合中的任何条目与正常条目进行比较,则可能会违反Object.equals(Object)合同的对称性和传递性要求映射条目,或者如果将此方法返回的集合与一组法线贴图条目进行比较(例如通过在法线贴图上调用该方法将返回)。 但是, Object.equals合同在基于身份的地图条目之间以及这些条目之间保留。

        Specified by:
        entrySet在接口 Map<K,V>
        Specified by:
        entrySetAbstractMap<K,V>
        结果
        该地图中包含的身份映射的集合视图
      • forEach

        public void forEach​(BiConsumer<? super K,? super V> action)
        描述从接口Map复制
        对此映射中的每个条目执行给定的操作,直到所有条目都被处理或操作引发异常。 除非实现类另有指定,否则按照进入设置迭代的顺序执行操作(如果指定了迭代顺序)。操作引发的异常被转发给调用者。
        Specified by:
        forEach在接口 Map<K,V>
        参数
        action - 为每个条目执行的操作
      • replaceAll

        public void replaceAll​(BiFunction<? super K,? super V,? extends V> function)
        描述从接口Map复制
        将每个条目的值替换为对该条目调用给定函数的结果,直到所有条目都被处理或该函数抛出异常。 函数抛出的异常被转发给调用方。
        Specified by:
        replaceAll在接口 Map<K,V>
        参数
        function - 应用于每个条目的功能