So, you want to make a calculation based on the contents of your object, which will give you a unique key, you can check the HashMap if there will be a “heavy” calculation, which you do not want to do twice already for this deep combination of fields.
hashCode only:
I believe that hashCode not suitable for use in the scenario you are describing.
hashCode should always be used with equals() . This is part of his contract, and this is an important part, because hashCode() returns an integer, and although you can try to distribute hashCode() as much as possible, it will not be unique for every possible object in the same class, except in very specific cases (easy for Integer , Byte and Character , for example ...).
If you want to see for yourself, try creating strings up to 4 letters long (lower and upper case) and see how many of them have the same hash codes.
HashMap therefore uses the hashCode() and equals() methods when it searches for things in a hash table. There will be elements that have the same hashCode() , and you can only tell if it is the same element or not by testing all of them using equals() for your class.
Using hashCode and equals together
In this approach, you use the object itself as a key in the hash map and assign the corresponding equals method to it.
To implement the equals method, you need to deeply examine all the fields. All their classes should have equals() , which corresponds to what you consider equal for the sake of your big calculation. Extra care must be taken when your objects implement the interface. If the calculation is based on calls to this interface, and different objects that implement the interface return the same value in these calls, then they should implement equals in a way that reflects this.
And their hashCode must match equals - when the values are equal, hashCode must be equal.
Then you create your equals and hashCode based on all of these elements. You can use Objects.equals(Object, Object) and Objects.hashCode( Object...) to save a lot of templates.
But is this a good approach?
As long as you can cache the result of hashCode() in an object and reuse it without computing, unless you mutate it, you cannot do this for equals . This means that calculating equals will be lengthy.
Therefore, depending on how many times the equals() method is called for each object, this will be exacerbated.
If, for example, you have 30 objects in the HashMap , but 300,000 objects go together and compare with them just to understand that they are equal to them, you will earn 300,000 heavy comparisons.
If you only have a few instances in which the object will have the same hashCode or fall into the same bucket in the HashMap , requiring comparison, then the equals() transition may work well.
If you decide to go this way, you need to remember:
If an object is a key in a HashMap , it should not be mutated , if any. If you need to change it, you may need to make a deep copy and save the copy on the hash map. Deep copying again requires consideration of all objects and interfaces inside to make sure that they can be copied at all.
Creating a unique key for each object
Back to the original idea, we found that hashCode not a good candidate for a key in a hash map. A better candidate for this would be a hash function like md5 or sha1 (or more advanced hashes like sha256, but you don't need cryptographic strength in your case), where collisions are much less common than just int . You can take all the values in your class, convert them to an array of bytes, hash it using such a hash function, and take the value of the hexadecimal string as the map key.
Naturally, this is not a trivial calculation. Therefore, you need to consider whether it really saves you a lot of time on the calculation that you are trying to avoid. This will probably be faster than repeating the equals() call to compare objects, since you only do this once for each instance with the values it had during the “big calculation”.
For a given instance, you can cache the result and not calculate it again if you do not mutate the object. Or you could just calculate it again just before doing a “big calculation."
However, you will need a “collaboration” of all the objects that you have in your class. That is, they should all be reasonably convertible to a byte array so that two equivalent objects produce the same bytes (including the same problem with the interface objects that I mentioned above).
You should also beware of situations in which you have, for example, two lines "AB" and "CD" that will give you the same result as "A" and "BCD", and then you will get the same hash for two different objects.