简体   繁体   English

IdentityHashMap 的用例

[英]Use cases for IdentityHashMap

谁能告诉IdentityHashMap的重要用例是什么?

Whenever you want your keys not to be compared by equals but by == you would use an IdentityHashMap.每当您希望您的键不被equals而是通过==进行比较时,您将使用 IdentityHashMap。 This can be very useful if you're doing a lot of reference-handling but it's limited to very special cases only.如果您进行大量引用处理,这可能非常有用,但仅限于非常特殊的情况。

The documentations says: 文件说:

A typical use of this class is topology-preserving object graph transformations, such as serialization or deep-copying.此类的典型用途是保留拓扑的对象图转换,例如序列化或深度复制。 To perform such a transformation, a program must maintain a "node table" that keeps track of all the object references that have already been processed.为了执行这样的转换,程序必须维护一个“节点表”来跟踪所有已经处理过的对象引用。 The node table must not equate distinct objects even if they happen to be equal.节点表不能等同于不同的对象,即使它们碰巧相等。 Another typical use of this class is to maintain proxy objects.此类的另一个典型用途是维护代理对象。 For example, a debugging facility might wish to maintain a proxy object for each object in the program being debugged.例如,调试工具可能希望为被调试程序中的每个对象维护一个代理对象。

One case where you can use IdentityHashMap is if your keys are Class objects.您可以使用 IdentityHashMap 的一种情况是您的键是 Class 对象。 This is about 33% faster than HashMap for gets!这比获取 HashMap 快约 33%! It probably uses less memory too.它也可能使用更少的内存。

You can also use the IdentityHashMap as a general purpose map if you can make sure the objects you use as keys will be equal if and only if their references are equal.如果您可以确保用作键的对象相等,当且仅当它们的引用相等时,您也可以将IdentityHashMap用作通用映射

To what gain?有什么收获? Obviously it will be faster and will use less memory than using implementations like HashMap or TreeMap .显然,与使用HashMapTreeMap等实现相比,它会更快并且使用更少的内存。


Actually, there are quite a lot of cases when this stands.实际上,这种情况出现的情况相当多。 For example:例如:

  • Enum s. Enum Although for enums there is even a better alternative:EnumMap尽管对于枚举,还有更好的选择:EnumMap
  • Class objects. Class对象。 They are also comparable by reference.它们也可以通过引用进行比较。
  • Interned String s.实习String s。 Either by specifying them as literals or calling String.intern() on them.通过将它们指定为文字或对它们调用String.intern()
  • Cached instances.缓存实例。 Some classes provide caching of their instances.一些类提供对其实例的缓存。 For example quoting from the javadoc of Integer.valueOf(int) :例如从Integer.valueOf(int)的 javadoc 引用:

    This method will always cache values in the range -128 to 127, inclusive...此方法将始终缓存 -128 到 127 范围内的值,包括...

  • Certain libraries/frameworks will manage exactly one instance of ceratin types, for example Spring beans.某些库/框架将只管理 ceratin 类型的一个实例,例如 Spring beans。
  • Singleton types.单例类型。 If you use istances of types that are built with the Singleton pattern, you can also be sure that (at the most) one instance exists from them and therefore reference equality test will qualify for equality test.如果您使用以单例模式构建的类型的实例,您还可以确保(最多)一个实例存在于它们中,因此引用相等性测试将有资格进行相等性测试。
  • Any other type where you explicitly take care of using only the same references for accessing values that were used to putting values into the map.任何其他类型,您明确地只使用相同的引用来访问用于将值放入映射中的值。


To demonstrate the last point:为了证明最后一点:

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));

Output will be, as expected (because we used the same Object references to query values from the map):输出将如预期的那样(因为我们使用相同的Object引用来查询地图中的值):

strkey: Key #0
java.lang.Object@1c29bfd: Key #1
1234567: Key #2

HashMap creates Entry objects every time you add an object, which can put a lot of stress on the GC when you've got lots of objects. HashMap 每次添加对象时都会创建 Entry 对象,当你有很多对象时,这会给 GC 带来很大的压力。 In a HashMap with 1,000 objects or more, you'll end up using a good portion of your CPU just having the GC clean up entries (in situations like pathfinding or other one-shot collections that are created and then cleaned up).在具有 1,000 个或更多对象的 HashMap 中,您最终将使用 CPU 的很大一部分,只是让 GC 清理条目(在诸如寻路或其他创建然后清理的一次性集合的情况下)。 IdentityHashMap doesn't have this problem, so will end up being significantly faster. IdentityHashMap 没有这个问题,所以最终会明显更快。

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

This is a practical experience from me:这是我的实践经验:

IdentityHashMap leaves a much smaller memory footprint compared to HashMap for large cardinalities.对于大基数,与 HashMap 相比,IdentityHashMap 留下的内存占用要小得多。

One important case is where you are dealing with reference types (as opposed to values) and you really want the correct result.一个重要的情况是您正在处理引用类型(而不是值)并且您确实想要正确的结果。 Malicious objects can have overridden hashCode and equals methods getting up to all sorts of mischief.恶意对象可能会覆盖hashCodeequals方法,从而引发各种恶作剧。 Unfortunately, it's not used as often as it should be.不幸的是,它没有像应有的那样经常使用。 If the interface types you are dealing with don't override hashCode and equals , you should typically go for IdentityHashMap .如果您处理的接口类型不覆盖hashCodeequals ,您通常应该选择IdentityHashMap

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM