简体   繁体   English

在计算 object 中的 hash 时,如何考虑 object 本身?

[英]How can I take into consideration the object itself when calculating a hash for an object in Java?

I was working on some algorithmic problems when I got to this and it seemed interesting to me.当我遇到这个问题时,我正在研究一些算法问题,这对我来说似乎很有趣。 If I have two lists (so two different objects), with the same values, the hashcode is the same.如果我有两个列表(所以两个不同的对象),具有相同的值,哈希码是相同的。 After some reading, I understand that this is how it should behave.经过一番阅读,我明白这就是它应该表现的方式。 For example:例如:

        List<String> lst1 = new LinkedList<>(Arrays.asList("str1", "str2"));
        List<String> lst2 = new LinkedList<>(Arrays.asList("str1", "str2"));
        System.out.println(lst1.hashCode() + " " + lst2.hashCode());
        ...........
        Result: 2640541 2640541

My purpose would be to differentiate between lst1 and lst2 in a list for example.例如,我的目的是区分列表中的 lst1 和 lst2 。

Is there a structure (like a HashSet for example) that takes into consideration the actual object and not only the values inside the object when calculating the hashcode for something?在计算某些东西的哈希码时,是否有一个结构(例如 HashSet)考虑实际的 object 而不仅仅是 object 内部的值?

Yes, you can use java's java.util.IdentityHashMap , or guava's identity hash set .是的,您可以使用 java 的java.util.IdentityHashMap番石榴的身份 hash set

The hashes of the two lists must be equal , because the objects are equal.两个列表的哈希值必须相等,因为对象是相等的。 But the identity map and set above are based on the identity of the list objects, not their hash.但是上面设置的标识 map 是基于列表对象的标识,而不是它们的 hash。

If I have two lists (so two different objects), with the same values, the hashcode is the same.如果我有两个列表(所以两个不同的对象),具有相同的值,哈希码是相同的。 After some reading, I understand that this is how it should behave.经过一番阅读,我明白这就是它应该表现的方式。

Yes, this is part of the specification of java.util.List .是的,这是java.util.List规范的一部分。

Is there a structure (like a HashSet for example) that takes into consideration the actual object and not only the values inside the object when calculating the hashcode for something?在计算某些东西的哈希码时,是否有一个结构(例如 HashSet)考虑实际的 object 而不仅仅是 object 内部的值?

My purpose would be to differentiate between lst1 and lst2 in a list for example例如,我的目的是区分列表中的 lst1 和 lst2

It is unclear what "in a list" means here.目前尚不清楚“在列表中”是什么意思。 For example, Collection.contains() and List.equals() are defined in terms or members' equals() methods, and likewise the behavior of List.remove(Object) .例如, Collection.contains()List.equals()是在术语或成员的equals()方法中定义的,同样是List.remove(Object)的行为。 Although distinct objects, your two List s will compare equal to each other, so those methods will not distinguish between them, neither directly nor as members of another list.尽管对象不同,但您的两个List将彼此比较,因此这些方法不会直接区分它们,也不会作为另一个列表的成员。 You can always compare them for reference equality ( == ), however, to determine that they are not the same object despite being equals() each other.但是,您始终可以比较它们的引用相等性 ( == ),以确定它们不是相同的 object 尽管彼此是equals()

As far as a collection that takes members' object identity into account, you could consider java.util.IdentityHashMap .至于将成员的 object 身份考虑在内的集合,您可以考虑java.util.IdentityHashMap Two such maps having keys and associated values that are pairwise equals() each other but not identical will not compare equals() to each other.两个这样的映射,其键和关联值彼此成对equals()但不相同,不会相互比较equals() Such sets will typically have different hash codes than each other, though that cannot be guaranteed.此类套件通常具有不同的 hash 代码,但不能保证这一点。 Note well, however, the warnings throughout the documentation of IdentityHashMap that although it implements the Map API, many of the behavioral details are inconsistent with the requirements of that interface.但是请注意, IdentityHashMap文档中的警告尽管它实现了Map API,但许多行为细节与该接口的要求不一致。


Note also that另请注意

  • most of the above is relevant only for collections whose members are of a type that overrides equals() and hashCode() .以上大部分内容仅与 collections 相关,其成员属于覆盖equals()hashCode()的类型。 The implementations of or inherited from Object differentiate between objects on a reference-equality basis, so the ordinary collections classes have no surprises for you there. Object的实现或继承于引用相等的基础上区分对象,因此普通的 collections 类对您来说没有什么意外。

  • identical string literals are not required to represent distinct objects, so the lst1 and lst2 in your example code may in fact contain identical elements, in the reference equality sense.不需要相同的字符串文字来表示不同的对象,因此示例代码中的lst1lst2实际上可能包含相同的元素,在引用相等意义上。

Not generally in collections, because you generally want two collections with all the same items to be equal (which is why they implement it like this- equals will return true and the hash codes are the same).通常不在 collections 中,因为您通常希望两个具有所有相同项目的 collections 相等(这就是为什么他们像这样实现它 - equals 将返回 true 并且 hash 代码相同)。

You can subclass a list and have it not do that, it would just not be widely useful and would cause a lot of confusion if other programmers read your code.您可以子类化一个列表并且让它不这样做,它不会被广泛使用,并且如果其他程序员阅读您的代码会引起很多混乱。 In that case, you'd just want equals to return the result of == and hashCode to return the integer value of the reference (the same thing that Object.equals does).在这种情况下,您只需要 equals 返回 == 和 hashCode 的结果以返回引用的 integer 值(与 Object.equals 所做的相同)。

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

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