模块  java.base
软件包  java.util

Class IdentityHashMap<K,​V>

  • 实现的所有接口
    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 ),当且仅当(k1==null ? k2==null : k1.equals(k2))两个密钥k1k2被认为是相等的。)

    这个类不是通用的Map实现! 虽然此类实现了Map接口,但它故意违反Map's一般合同,该合同要求在比较对象时使用equals方法。 此类仅用于需要引用相等语义的罕见情况。

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

    此类提供所有可选的映射操作,并允许null值和null键。 这个类不保证地图的顺序; 特别是,它不保证订单会随着时间的推移保持不变。

    假设系统标识散列函数( System.identityHashCode(Object) )在存储桶之间正确地分散元素,则put为基本操作( getput )提供恒定时间性能。

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

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

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

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

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

    请注意,迭代器的快速失败行为无法得到保证,因为一般来说,在存在不同步的并发修改时,不可能做出任何硬性保证。 失败快速迭代器以尽力而为的方式抛出ConcurrentModificationException 因此,编写依赖于此异常的程序以确保其正确性是错误的: 故障快速迭代器应仅用于检测错误。

    实现说明:这是一个简单的线性探测哈希表,如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 - m映射放入此映射的映射
        异常
        NullPointerException - 如果指定的映射为null
    • 方法详细信息

      • size

        public int size()
        返回此标识哈希映射中键 - 值映射的数量。
        Specified by:
        size在界面 Map<K,​V>
        重写:
        size在类 AbstractMap<K,​V>
        结果
        此映射中键 - 值映射的数量
      • isEmpty

        public boolean isEmpty()
        如果此标识哈希映射不包含键 - 值映射,则返回 true
        Specified by:
        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操作来区分这两种情况。

        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>
        重写:
        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>
        重写:
        putAll在类 AbstractMap<K,​V>
        参数
        m - 要存储在此映射中的映射
        异常
        NullPointerException - 如果指定的映射为null
      • remove

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

        public void clear()
        从此映射中删除所有映射。 此调用返回后,映射将为空。
        Specified by:
        clear在界面 Map<K,​V>
        重写:
        clear在类 AbstractMap<K,​V>
      • equals

        public boolean equals​(Object o)
        将指定对象与此映射进行比较以获得相等性。 如果给定对象也是映射,则返回true ,并且两个映射表示相同的对象引用映射。 更正式的是,这张地图等于另一张地图m当且仅当this.entrySet().equals(m.entrySet())

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

        Specified by:
        equals in interface 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实例m1m2 ,根据m2的一般合同的要求

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

        Specified by:
        hashCode in interface 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.removeSet.removeremoveAllretainAll ,和clear方法。 它不支持addaddAll方法。

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

        仅当指定对象是包含与返回集完全相同的对象引用的集时,返回集的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>
        结果
        此映射中包含的标识映射的set视图