IdentityHashMap的用例

Ton*_*ony 57 java

请问有谁可以告诉重要的用例是IdentityHashMap什么?

B.E*_*.E. 34

每当您希望您的密钥不被比较时equals,==您将使用IdentityHashMap.如果您正在进行大量的参考处理,这可能非常有用,但它仅限于非常特殊的情况.

  • 此外,因为身份不变量(o == o => true,对于任何o),即使关键对象被突变*,也可以使用IdentityHashMap*.但是你没有使用可变键......是吗?(也许我应该坐在角落里哭泣.) (2认同)

sri*_*ris 30

单证说:

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

  • 我来自文档,寻找关于SO的解释 (12认同)

Nat*_*teS 21

如果您的密钥是Class对象,则可以使用IdentityHashMap的一种情况.获得的速度比HashMap快33%!它也可能使用更少的内存.

  • 您是否有任何来源/基准来支持该声明? (2认同)

icz*_*cza 19

如果可以确保用作键的对象在当且仅当它们的引用相等时才相等,您也可以将其IdentityHashMap用作通用映射 .

获得了什么?显然它会比使用或类似的实现更快并且将使用更少的内存.HashMapTreeMap


实际上,在这种情况下,有很多案例.例如:

  • Enum秒.虽然对于枚举,甚至有更好的选择:EnumMap
  • Class对象.它们也可以通过参考进行比较.
  • 实习String秒.通过将它们指定为文字或调用String.intern()它们.
  • 缓存的实例.有些类提供其实例的缓存.例如,引用javadoc Integer.valueOf(int):

    此方法将始终缓存-128到127范围内的值,包括...

  • 某些库/框架将只管理一个ceratin类型的实例,例如Spring bean.
  • 单身人士类型.如果使用使用Singleton模式构建的类型的istances ,您还可以确保(最多)存在一个实例,因此引用相等性测试将有资格进行相等性测试.
  • 您明确处理的任何其他类型,仅使用相同的引用来访问用于将值放入映射的值.


为了证明最后一点:

Map<Object, String> m = new IdentityHashMap<>();

// Any keys, we keep their references
Object[] keys = { "strkey", new Object(), new Integer(1234567) };

for (int i = 0; i < keys.length; i++)
    m.put(keys[i], "Key #" + i);

// We query values from map by the same references:
for (Object key : keys)
    System.out.println(key + ": " + m.get(key));
Run Code Online (Sandbox Code Playgroud)

输出将如预期的那样(因为我们Object对地图中的查询值使用了相同的引用):

strkey: Key #0
java.lang.Object@1c29bfd: Key #1
1234567: Key #2
Run Code Online (Sandbox Code Playgroud)


Eli*_*Eli 16

每次添加对象时,HashMap都会创建Entry对象,当您拥有大量对象时,这会给GC带来很大的压力.在具有1,000个或更多对象的HashMap中,您最终将使用大部分CPU来清理GC(在路径查找或其他一次性集合中创建然后清理).IdentityHashMap没有这个问题,因此最终会明显加快速度.

在此处查看基准:http://www.javagaming.org/index.php/topic,21395.0/topicseen.html


小智 12

这是我的实践经验:

与HashMap相比,IdentityHashMap为大基数留下了更小的内存占用量.


Tom*_*ine 5

一种重要的情况是,您正在处理引用类型(而不是值)并且您确实想要正确的结果。恶意对象可能会被覆盖hashCode,并且equals方法可能会造成各种恶作剧。不幸的是,它没有得到应有的频繁使用。如果您正在处理的接口类型不覆盖hashCodeequals,那么您通常应该选择IdentityHashMap