Java equals and hashCode methods - technical constraints - java

I've got question about java's equals(Object o) and hashCode() methods. What are the technical constraints of implementation this both methods? Is there something that I can't do during implement this methods?

None. It's just two methods in Object class. You could even change an object's state within this methods and this will freak out every developer and system but it's still valid from technical point of view.

You can technically anything inside them you can do in any other methods.
Instead what you concern yourself with are the practical and contractual obligations of the methods.
Good rules of thumb:
If you override one, override the other.
Variables used in one should be used in the other.

a given object must consistently report the same hash value
two objects which equals() says are equal must report the same hash value - so no timestamps in the hashcode :).
Two unequal objects can also have the same hashcode, though it is better to make the hashcode difficult to repoduce.

All you need to remember, is:
those constrains are very important
all are very well documented in javadoc for Object.hashCode() and Object.equals()
Make sure you understand it every time you override any of those methods.

Is there something that I can't do during implement this methods?
Well, as a rule of thumb (and as already #RHT mentioned above and #Antti Sykäri explains here) do your future self a favor and always use EqualsBuilder and HashCodeBuilder from the Apache Commons Lang library. Because, quite frankly, at least in my case I never get to remember all the nitty-gritty details that a correct implementation would require. ;-)

Related

Effective Java: should I override equals() and hashCode() if the objects I'm creating are never compared with each other?

If the objects I create are not used for comparisons such as list.contains(new Employee("MM")), and also if those objects will only be stored in Lists returned from a database such as List<Employee>employeeList = employeeService.getEmployeeList(); then do I need to override equals() and hashCode() in Employee class?
No, you do not need to override .equals() and .hashCode() if you don't need a custom definition of equality. As long as you intend to treat every instance of your class as un-equal to other instances the defaults will work fine. You can store such objects in Lists and even in hash-based collections such as HashMaps and HashSets - both classes have no problems with the default Object notion of equivalence.
Furthermore for many classes you shouldn't override these methods. Many common design patterns will include classes that aren't intended to ever be equivalent, such as factories, singletons, and state machines. Defining a custom notion of equality for such classes can introduce strange bugs, or at a minimum simply be unnecessary boilerplate.
On the other hand value types, or classes intended specifically to be a structured representation of some sort of data should almost always override .equals() and .hashCode() (and possibly implement Comparable as well), because it's what users of these sort of classes are likely to expect. The Auto/Value project makes creating such value types really painless; if that's the type of class you're constructing I'd strongly encourage you to use it.
If you know you will never be using the object as a key in a HashMap or will never be putting it in any sort of Set, or never doing anything with it where you will do any object comparison other than "are these references referring to literally same instance or not", then you do not have to override equals() and hashCode().
And if that's not the case and you do have to override them, then do consider letting your IDE generate the overrides rather than doing it manually -- especially for hashCode(). And be aware that when having the IDE generate these, you can tell the IDE which fields to include and which fields not to include, which even further reduces any need to write the overrides manually.
As QuantumMechanic had said above, you do not need to override equals() and hashcode().
However, if the Employee class is going to be shared with other people, it's a good idea to add equal and hashcode so that it is easier for other people to use.
Also, Eclipse can generate these functions by right clicking -> Source -> Generate hashCode() and equals()
Good luck!
Why overriding Equals Method:
If you object needs to be stored on Collection i.e List, you should override equals method since when you will use indexOf, lastIndexOf etc API method as those api methods internally uses equals method. If you dont override equal method, then you might get those object back from collections since identity checking is not the right way to get the object back from Collections.
Why overriding hashCode Method:
If your object needs to be stored in a set or as key object in a map collection, you must override HashCode and Equals both becuase both methods are used to get the object back from those collections.

Why doesn't Java have an interface similar to Comparator, but for hashing? [duplicate]

This question already has answers here:
Why there is no Hashable interface in Java
(2 answers)
Closed 9 years ago.
In Java, the Comparator interface allows a client to specify an equals() and compare() method for any type. A Comparator can be passed to most (or maybe all) collections that require sorting, and the methods in the Comparator will be used instead of the methods of the specified class. This allows clients to sort objects in a way that is different from their natural ordering, or even to sort objects that don't have a natural ordering (i.e. don't implement Comparable).
Why isn't there a similar interface for hashing? It could specify two methods, hashCode() and equals(), and be useful for HashSets or HashMaps in the same way Comparators are useful for sorting.
Edit: For those who marked this question a duplicate of this other question, I would mention that the other question asks why hashCode is included in every class instead of an interface, while this question is about abstracting the hashing function to allow multiple implementations of it.
Answer Edit: The best methods of getting this functionality seem to be:
-If you're ok using an external library and/or are already using Guava (which is a fantastic library for a lot of reasons), Guava has an Equivalence class that allows this.
-If you don't want to use an external library, you can use a custom built adapter, similar to what is done in the top answer on this SO question.
Questions of the form
"Why doesn't Java have XXX"
are difficult to answer objectively except with a generic
"We don't know because nobody here was in the room when the decision was made."
In this case:
On the face of it, this requirement can be implemented ... from a technical perspective.
This requirement has been proposed numerous times via RFEs. The most direct one is http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=6435963. The RFE is marked as WONT FIX, though no particular reason is given.
This requirement could be, and has been adequately met by 3rd party libraries.
My reading of this is that it is not supported because it has not been deemed important enough for enough people that it needs to be supported. I'd say they made a reasonable call on that.
I also think that such an interface would be handy, specifically as a way to consider different kinds of equalities in collections. It should be similar to the way that you can make an object Comparable, but still override that behavior in a specific collection by providing some other Comparator.
As was pointed out in this question, Guava has an Equivalence class that provides a way to do this, by wrapping your class and letting you define at the wrapper level what 'equality' means in this context.
If your question is really why this didn't happen at language design time... well, hey, James Gosling and company are only human, right?
Hashing has really just one requirement: Being like a hash method. So you can implement it for a type without knowing who will use it in what way and for what purpose. So the hash method on the object itself is sufficient.
Equals on the other hand has different meanings in different contexts. For example you can sort people by first name, last name, age, size, weight, time of membership in a club ... So it makes sense to have different implementations of equal (and 'less than') for a single class.
Of course nothing keeps you from creating such an interface and using it ...
You can always change the hashcode() to say how the HashMap arranges your object in Map and improve its performence by implementing an effective hashcode method in your class.
How HashMap performs addition and removal from a hashed data is internal to HashMap and changing it would basically mean changing add,remove methods etc.
Also sorting is a common feature that is used more often and for a rare case when you really want to change how hashing happens in a map then there is always the option to extend a Map.
Let me try to say how I see it, why.
Briefly - you often need to sort a list objects, but you rare (if ever) need to cross compare identities of a list of object.
In Object, method hashCode is a secondary, helpful method, which main purpose is to serve the equals method. The agreement is that if for two objects hashCode returns different values, equals mustn't return true.
So, methods hashCode and equals serve to establish the identity of an object.
Method compareTo (in both Comparable and Comparator) serves another general purpose. It defines objects order, not their identity.
Resume - compareTo defines how the objects are ordered, hashCode (together with equals) defines objects identity.
Again - practice contribution is that you often have to sort a group of objects, but you rare (if ever) have to take a group of objects and cross compare their identities.

Java hashCode() method override is not needed if we don't use hashmap or hashset

My co-worker was overriding the equals() method. My response was, have you also overridden the hashCode() method? His response was because we won't use hash map or hash set, it shouldn't really matter if we override hashCode(). Is that correct?
Yes he is factually right - however, if you need to put your objects in a hash-based collection one day, you will have to add hashcodes everywhere, which can be annoying + on that day you might implement your hashcode incorrectly (i.e. not consistent with equals) because you miss some subtlety in the equals method...
Considering that most IDEs provide an auto equals/hashcode generation feature, I see little reason not to create both.
Another way to look at it is: when you override a method from a parent class, you should follow the contract defined by that parent class. In the case of Object, the javadoc of equals is pretty clear:
Note that it is generally necessary to override the hashCode method whenever this method is overridden, so as to maintain the general contract for the hashCode method, which states that equal objects must have equal hash codes.
So unless you have a real design reason not to override hashcode, the default decision should be to follow the parent class contract and override neither or both.
If you override equals(), do override hashCode() as well. Even if you don't use hashCode() now, you or somebody else might use it.
For more on this topic, check the excellent SO answer
It's a code smell. Findbugs for example will warn you if you override either hashCode or equals without overriding the other. You should override both so that they are consistent with one another (that is, a.equals(b) => a.hashCode() == b.hashCode()).
A little effort now may save a lot of headaches later.
You must override hashCode in every class that overrides equals. Failure to do so will result in a violation of the general contract for Object.hashCode, which will prevent your class from functioning properly in conjunction with all hash-based collections, including HashMap, HashSet, and Hashtable.
Effective Java Item 9: Always override hashCode when you override equals.
If your class is a public class then you can not control how your classes will be used in future development. Without looking into source code (or through reflection) there is no way to know whether this class has overriden the hasCode method or not and the user will be surprised by the result if they use it in any hash based collections.
Actually assume that you create two different objects without overriding equals and hashCode methods. And then if you call equals method java calls hashCode method implicitly then checks the equality of hashcodes.
Overriding hashCode method is enough for checking equality of two objects. And it will be useful for future. You can use this class on collections.
Otherwise if you implement just equal method, it will solve just equality of two objects not more.
General:
only override those methods which you want to use in your own way and also those methods which are affected by this overriding.
Specific to your Ques:
From java docs,
Note that it is generally necessary to override the hashCode method
whenever equals() method is overridden, so as to maintain the general
contract for the hashCode method, which states that equal objects must
have equal hash codes.
Equals

How to proceed if equals was overridden but not hashCode?

I've come across some third-party code that overrides equals() but not hashCode(). Would I be right in thinking that as long as I do not use these objects as Map keys, this is harmless?
I could of course add the override for hashCode (in several objects) but then I would be creating more work for myself every time I receive an upgrade.
Other than Map you need to check :
if you are using instance of this class in your ORM, more info at, on the hashcode implementation you can use Apache's HashCodeBuilder.
Comparator, Comparable on this class cannot use hashcode to check for comparison.
Pragmatic Concept
Hope this helps.
I don't think you can assume that it's harmless. HashMap will be using hashCode.
I'd find another library. If they can't override equals and hashCode properly, what else are they doing wrong?
If the objects do not extend another class (so they inherit from Object) then their hashCode is a function of their object reference. That means if you use them as the key in a HashMap (or as an element of a HashSet), you can only expect to find them if you use the exact same instance of the object to do the look up.
The "contract" is that if two objects are equal then they must have the same hashCode, however your analysis is correct - hashCode only matters in the collections API (HashSet, HashMap, etc.). You should know how you will be using the API so if you know you will not be using the hashCode, and you do not expose this objects of the API in your public API, then there is no problem.

Additional methods in the Object Class

The Object class has a number of methods such as equals, hashCode, notify, wait etc.
What methods do you think are missing from the Object class and why? Are there any additional methods you wish it had?
I don't think it should have any extra methods... in fact, I think various methods that are there shouldn't be there in the first place.
One problem in Java is that a lot of types (such as HashMap) always use the hash code and equality methods on the keys directly - it would be much better if Java had an interface like .NET's IEqualityComparer<T> that anything wanting to perform hashing/equality comparisons could delegate to.

Categories

Resources