java IdentityHashMap 的用例

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/838528/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 13:59:00  来源:igfitidea点击:

Use cases for IdentityHashMap

java

提问by Tony

Could anyone please tell what are the important use cases of IdentityHashMap?

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

采纳答案by sris

The documentationssays:

单证说:

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.

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

回答by B.E.

Whenever you want your keys not to be compared by equalsbut by ==you would use an IdentityHashMap. This can be very useful if you're doing a lot of reference-handling but it's limited to very special cases only.

每当您希望您的密钥不被比较时equals==您将使用 IdentityHashMap。如果您要进行大量引用处理,这将非常有用,但仅限于非常特殊的情况。

回答by NateS

One case where you can use IdentityHashMap is if your keys are Class objects. This is about 33% faster than HashMap for gets! It probably uses less memory too.

您可以使用 IdentityHashMap 的一种情况是您的键是 Class 对象。这比获取 HashMap 快约 33%!它也可能使用更少的内存。

回答by icza

You can also use the IdentityHashMapas a general purpose mapifyou can make sure the objects you use as keys will be equal if and only iftheir references are equal.

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

To what gain? Obviously it will be fasterand will use less memory than using implementations like HashMapor TreeMap.

有什么收获?显然,它会比使用或 之类的实现更快并且使用更少的内存。HashMapTreeMap



Actually, there are quite a lot of cases when this stands. For example:

其实,这种情况出现的情况还不少。例如:

  • Enums. Although for enums there is even a better alternative: EnumMap
  • Classobjects. They are also comparable by reference.
  • Interned Strings. Either by specifying them as literalsor calling String.intern()on them.
  • Cached instances. Some classes provide caching of their instances. For example quoting from the javadoc of Integer.valueOf(int):

    This method will always cache values in the range -128 to 127, inclusive...

  • Certain libraries/frameworks will manage exactly one instance of ceratin types, for example Spring beans.
  • Singleton types. If you use istances of types that are built with the Singletonpattern, 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.
  • Enums。尽管对于枚举,还有更好的选择:EnumMap
  • Class对象。它们也可以通过引用进行比较。
  • 实习String秒。通过将它们指定为文字或调用String.intern()它们。
  • 缓存实例。一些类提供对其实例的缓存。例如从 javadoc 引用Integer.valueOf(int)

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

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



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 Objectreferences to query values from the map):

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

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

回答by Eli

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. 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). IdentityHashMap doesn't have this problem, so will end up being significantly faster.

HashMap 每次添加对象时都会创建 Entry 对象,当你有很多对象时,这会给 GC 带来很大的压力。在具有 1,000 个或更多对象的 HashMap 中,您最终将使用 CPU 的很大一部分,只是让 GC 清理条目(在诸如寻路或其他创建然后清理的一次性集合的情况下)。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

回答by rfang

This is a practical experience from me:

这是我的实践经验:

IdentityHashMap leaves a much smaller memory footprint compared to HashMap for large cardinalities.

对于大基数,与 HashMap 相比,IdentityHashMap 留下的内存占用要小得多。

回答by Tom Hawtin - tackline

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 hashCodeand equalsmethods getting up to all sorts of mischief. Unfortunately, it's not used as often as it should be. If the interface types you are dealing with don't override hashCodeand equals, you should typically go for IdentityHashMap.

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