简体   繁体   中英

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.

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?

Yes, you can use java's java.util.IdentityHashMap , or guava's identity 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.

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 .

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?

My purpose would be to differentiate between lst1 and lst2 in a list for example

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) . 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. You can always compare them for reference equality ( == ), however, to determine that they are not the same object despite being equals() each other.

As far as a collection that takes members' object identity into account, you could consider 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. Such sets will typically have different hash codes than each other, though that cannot be guaranteed. 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.


Note also that

  • most of the above is relevant only for collections whose members are of a type that overrides equals() and 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.

  • 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.

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

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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