Why does Comparator declare equals? - java

The Comparator interface has its own equals() method. Any class will get equals() by default through Object class. What is the need to have equals() method inside an interface?

Comparator refines the contract of Object.equals: It has to satisfy the constraints set out by Object.equals and then some.
Additionally, this method can return true only if the specified object is also a comparator and it imposes the same ordering as this comparator. Thus, comp1.equals(comp2) implies that sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) for every object reference o1 and o2.
Declaring an equals inside Comparator allows you to document this in the form of javadoc.
Note that the documentation of the API also serves as the contract, so it's not just cosmetics here. It's explicit constraints that other code and your code can rely on.
In similar situations where you have less established methods, it may also serve as documenting an intent. I.e., Interface.method should be there, regardless of how its super interfaces evolves.

From the Java documentations, the reason why Comparator has it's own equals() method:
However, overriding this method may, in some cases, improve performance by allowing programs to determine that two distinct comparators impose the same order.

Read its javadoc. It's there only to explain what equals() must return if you choose to override it in a class implementing Comparator. You might think that no comparator can be equal to any other, but it's not the case. You might think that two comparators are equal if they return the same thing for any arguments, but it's not the case. The javadoc explains that two comparators are equal if they impose the same ordering, whatever the arguments given. The javadoc also says:
Note that it is always safe not to override Object.equals(Object)
Most of the time, you don't override equals() in comparators.

from the docs:
it is always safe not to override Object.equals(Object). However, overriding this method may, in some cases, improve performance by allowing programs to determine that two distinct comparators impose the same order.

Technically, the declaration of the method is redundant (the compiler does not care), but...
Declaring the equals method in this interface makes it part of the contract between caller and different Comparators and allows it to specify/extend its semantics.
It specifies that two Comparators are equal only if they impose the same ordering with their compare() method. This extends the semantics of Object.equals() and must therefore be documented in the interface.

Putting an Object method in an interface declaration allows Javadoc
declaration of the meaning equals is required to have in classes that
implement the interface.

Comparator interface have their own equals() method
Well,. first of all, it should be clear that whenever you implement Comparable interface you should provide your program to decide when objects are equal, less or greater.
I am quite confuse about have equals() inside Comparator. Any class will get equals() by default through Object class.
The equals() method implementation u inherit from Object class only checks whether the two referances point to the same object or not. It dosn't apply any comparison. It's you who will provide in your class (or possibly in your Interface) the criteria for objects to be equal.
Then what is need to have equals() method inside an interface?
Obviously , whenever you implement when objects are less , greater than you must implement when they are equal. so rather than relying on default Object equals() method you should provide your logic to check equality

The equals() method in Comparator is provided to force a user implementing the Comparator interface to implement equals() with some additional rules and constraints in addition to the ones already applied on equals() from Object.
The additional rule being:
This method must obey the general contract of Object.equals(Object).
Additionally, this method can return true only if the specified object
is also a comparator and it imposes the same ordering as this
comparator. Thus, comp1.equals(comp2) implies that
sgn(comp1.compare(o1, o2))==sgn(comp2.compare(o1, o2)) for every
object reference o1 and o2.

Related

Overriding equals method to compare functional interfaces

I am implementing equals method for a class, which has a member of a Functional Interface type. I do not have a separate class for the concrete implementation of the interface, and I use lambda expression to create and set the interface variable. I want the equals method of the class to take into consideration, the code, which was provided via lambda expression. Different implementations must must not return equal. Is there a way to achieve this properly? Since I did not find any links related to this requirement I am doubting whether such a practice is recommended, even if it is possible to achieve the same. What is the best thing to do?

Why does the Collection interface have equals() and hashCode()?

Why does the Collection interface have equals(Object o) and hashCode(), given that any implementation will have those by default (inherited from Object) ?
From the Collection JavaDoc:
While
the Collection interface adds no stipulations to the general contract
for the Object.equals, programmers who implement the Collection
interface "directly" (in other words, create a class that is a
Collection but is not a Set or a List) must exercise care if they
choose to override the Object.equals. It is not necessary to do so,
and the simplest course of action is to rely on Object's
implementation, but the implementor may wish to implement a "value
comparison" in place of the default "reference comparison." (The List
and Set interfaces mandate such value comparisons.)
The general contract for the Object.equals method states that equals
must be symmetric (in other words, a.equals(b) if and only if
b.equals(a)). The contracts for List.equals and Set.equals state that
lists are only equal to other lists, and sets to other sets. Thus, a
custom equals method for a collection class that implements neither
the List nor Set interface must return false when this collection is
compared to any list or set. (By the same logic, it is not possible to
write a class that correctly implements both the Set and List
interfaces.)
and
While the Collection interface adds no stipulations to the general contract for the Object.hashCode method, programmers should take note that any class that overrides the Object.equals method must also override the Object.hashCode method in order to satisfy the general contract for the Object.hashCode method. In particular, c1.equals(c2) implies that c1.hashCode()==c2.hashCode().
To answer your specific question: why does it have these methods? It's done simply for convenience to be able to include Java Docs giving hints as to what implementers should do with these methods (e.g. comparing equality of values rather than references).
To add to the other great answers. In the Collections interface, the equals method is defined in that interface to make some decisions in the way equaling two instances of collection should work. From the JAVA 8 documentation:
More generally, implementations of the various Collections Framework
interfaces are free to take advantage of the specified behavior of
underlying Object methods wherever the implementor deems it
appropriate.
So you don’t add methods from the Object class for any other reason that giving more definitiveness to the java doc. This is the reason why you don’t count those methods in the abstract methods in the abstract methods of an interface.
Moreover, in JAVA 8, along the same line of reasoning, default methods from the Object class are not allowed and will generate a compile error. I believe it’s was done to prevent this type of confusion. So if you try to create a default method called hashCode(), for example, it will not compile.
Here is a more in-depth explanation for this behavior in JAVA 8 from the Lambda FAQ:
An interface cannot provide a default implementation for any of the
methods of the Object class. This is a consequence of the “class wins”
rule for method resolution: a method found on the superclass chain
always takes precedence over any default methods that appear in any
superinterface. In particular, this means one cannot provide a default
implementation for equals, hashCode, or toString from within an
interface.
This seems odd at first, given that some interfaces actually define
their equals behavior in documentation. The List interface is an
example. So, why not allow this?
One reason is that it would become more difficult to reason about when
a default method is invoked. The current rules are simple: if a class
implements a method, that always wins over a default implementation.
Since all instances of interfaces are subclasses of Object, all
instances of interfaces have non-default implementations of equals,
hashCode, and toString already. Therefore, a default version of these
on an interface is always useless, and it may as well not compile.
Another reason is that providing default implementations of these
methods in an interface is most likely misguided. These methods
perform computations over the object’s state, but the interface, in
general, has no access to state; only the implementing class has
access to this state. Therefore, the class itself should provide the
implementations, and default methods are unlikely to be useful.
Just to add to the great answers above, it makes sense to have the 'equals' or `hashCode' methods in this scenario:
Collection<Whatever> list1 = getArrayList();
Collection<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}
In the absence of the equals method in the interface, we'll be forced to use concrete types, which is generally not a good practice :
ArrayList<Whatever> list1 = getArrayList();
ArrayList<Whatever> list2 = getAnotherArrayList();
if(list1.equals(list2)){
// do something
}

What is point of implementing the Comparable interface in my classes?

I don't get the point of implementing the Comparable interface, since I can't use the comparison operators <, <=, >=, and > for my custom classes like I would be able to with operator overriding in languages like C++; I still have to call the compareTo method directly.
I could write my own boolean methods like isEqual or bigger, which would be just as useful, if not more so, than the compareTo method.
Am I missing something? What is the point of implementing it?
The Comparable interface provides a means of communication to the implemented sorting algorithms, which would be impossible using custom methods for comparison.
The point of implementing Comparable is being able to sort arrays, Collections, etc... based on different criteria.
Other classes can take a parameter of type Comparable. They will not know your special methods, but they know the interface and can use it if implemented.
As an example, the method Collections.sort() can make use of an Comparable: http://docs.oracle.com/javase/7/docs/api/java/util/Collections.html#sort(java.util.List,%20java.util.Comparator)

Why is it not necessary to override both methods of interface Comparator in Java

We know that it is necessary to implement all methods of an interface, if we want to make an object of that class. But why is it not necessary to implement both the methods compare() and equals() of interface Comparator in java?
I agree that the purpose is solved but even then why is it not mandatory to override equals() if we override compare()?
Since all classes implicitly extend Object every implementation of a Comparator has an equals method, because every Object has one.
It would be the same if you define an interface with a toString() method.
public interface ToString {
public String toString();
}
public class SomeClass implements ToString {
// toString implicitly implemented, because Object defines it
}
When you look at the class it says "implements ToString" and this is true, isn't it?
Because it is already overridden by java.lang.Object on every object you can create.
Every object implicitly has an equals from Object (as every object is a sub-type of Object) - and since it's a virtual method, standard Java polymorphism takes over.
Now, Comparator#equals imposes an additional restriction, which is why it is specified as part of the interface.
..this method can return true only if the specified object is also a comparator and it imposes the same ordering as this comparator.
However, since the coverse need to be true, then not overloading equals doesn't break the new requirement.
Note that it is always safe not to override Object.equals(Object).. [as then different comparator instances will never be equal].

Should we always override equals?

When writing one's own classes, is it always necessary to override equals(Object o)?
If I don't, will it automatically check that all the fields are the same? Or does it just check if the two variables point to the same object?
If one is writing a class that is going to have its objects be compared in some way, then one should override the equals and hashCode methods.
Not providing an explicit equals method will result in inheriting the behavior of the equals method from the superclass, and in the case of the superclass being the Object class, then it will be the behavior setforth in the Java API Specification for the Object class.
The general contract for providing an equals method can be found in the documentation for the Object class, specifically, the documentation of the equals and hashCode methods.
Only override equals() if it makes sense. But obviously if you override equals() you need to ensure that the hashcode() contract isn't broken, meaning if two objects are equal they must have the same hash code.
When does it make sense? When Object.equals() is insufficient. That method basically comes down to reference identity, meaning two objects are the same object so:
a.equals(b) iff q == b
Numbers are an obvious example when it makes sense because Integer(10) should equal another Intger(10).
Another example could be when you're representing database records. Let's say you have Student records with a unique integer ID, then it might be sufficient implementation of equals to simply compare the ID fields.
The equals method for class Object implements the most discriminating possible equivalence relation on objects; that is, for any non-null reference values x and y, this method returns true if and only if x and y refer to the same object (x == y has the value true).
To test whether two objects are equal in the sense of equivalency (containing the same information), you must override the equals() method.You should always override the equals() method if the identity operator is not appropriate for your class.
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.
While you shouldn't rely on an IDE, Eclipse provides this canned functionality by pressing alt + shift + s and selecting the equals and hashCode menu options. There is also a toString option. Effective Java by Josh Bloch has good info on this subject. The link will take you to the chapter hosted on Google Books that discusses this topic.

Categories