Week 80 — Which mechanisms does Java provide for comparing objects?

Question of the Week #80
Which mechanisms does Java provide for comparing objects?
11 Replies
Eric McIntyre
Eric McIntyre5mo ago
Java provides Comparable interface. It is mainly for comparing two objects. In order for a class to be comparable, it has to implement this interface. Specifically, the compareTo method. It returns -1 if x < y and 0 of x == y and +1 ix x > y Here is an example: In this example students are compared using their age.
class Student implements Comparable<Student>{
int rollno;
String name;
int age;

Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}

public int compareTo(Student anotherStudent) {
if( age < anotherStudent.age ) {
return -1;
}

if( age > anotherStudent.age ) {
return 1;
}

return 0;
}
}
class Student implements Comparable<Student>{
int rollno;
String name;
int age;

Student(int rollno,String name,int age){
this.rollno=rollno;
this.name=name;
this.age=age;
}

public int compareTo(Student anotherStudent) {
if( age < anotherStudent.age ) {
return -1;
}

if( age > anotherStudent.age ) {
return 1;
}

return 0;
}
}
Eric McIntyre
Eric McIntyre5mo ago
You can also use the Comparator interface to create comparators that are not tied with a class.
Submission from satinos
Eric McIntyre
Eric McIntyre5mo ago
Comparable in which we can compare objects by using compareTo method and we can override this method to compare according to our need
Submission from ajay19
Eric McIntyre
Eric McIntyre5mo ago
Comparable.compare method, Comparators can be used to compare objects which is also used by equals methods of classes
Submission from h31l0w0r1d
Eric McIntyre
Eric McIntyre5mo ago
To compare objects, we can use .equals() method eg: obj1.equals(obj2)
Submission from .siddhant1
Eric McIntyre
Eric McIntyre5mo ago
da equals method da compareTo method da == check (compare address) da comparator interface
Submission from pricez
Eric McIntyre
Eric McIntyre5mo ago
1.Comparable Interface: This is used for natural ordering of objects. A class implements the Comparable interface and overrides the compareTo method. public class MyClass implements Comparable<MyClass> { private int value; public MyClass(int value) { this.value = value; } @Override public int compareTo(MyClass other) { return Integer.compare(this.value, other.value); } } 2.Comparator Interface: This is used for defining multiple comparison strategies or if the class does not have a natural ordering. A class implements the Comparator interface and overrides the compare method. 3.equals() and hashCode() Methods: The equals method checks for equality, and hashCode is used for hashing purposes. public class MyClass { private int value; public MyClass(int value) { this.value = value; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null || getClass() != obj.getClass()) return false; MyClass myClass = (MyClass) obj; return value == myClass.value; } @Override public int hashCode() { return Objects.hash(value); } }
⭐ Submission from harshtarsariya
Eric McIntyre
Eric McIntyre5mo ago
For straight equality, Java provides 2 mechanisms: the equality operator, ==, and the Object.equals(Object) method. The equality operator is part of the language itself. It is most useful for comparing primitive values, such as:
if (x == 27) {
System.out.println("x is 27");
}
if (x == 27) {
System.out.println("x is 27");
}
However, when used for object references, the equality operator only compares that the references themselves refer to the same object on the heap. For instance, the following code will print "Not equal", even though both variables represent the same logical date:
var date1 = LocalDate.of(2024, 6, 24);
var date2 = LocalDate.of(2024, 6, 24);
if (date1 == date2) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
var date1 = LocalDate.of(2024, 6, 24);
var date2 = LocalDate.of(2024, 6, 24);
if (date1 == date2) {
System.out.println("Equal");
} else {
System.out.println("Not equal");
}
For objects, you usually want to use the .equals() method, which can be overridden by classes to perform a "semantic" equality comparison. Given the above objects, if we changed the if comparison to:
(date1.equals(date2))
(date1.equals(date2))
... then it would in fact print "Equal". As a side note, classes that override the .equals() method should also override the .hashCode() method. See the JavaDoc on the java.lang.Object class for details. Another mechanism for comparing objects are the java.lang.Comparable<T> and java.util.Comparator<T> interfaces. The Comparable<T> interface allows a class to define comparison semantics against other instances of that class.^ It defines a single required method, compareTo(T other), which returns a negative, positive, or zero, depending on whether this is "less than", "greater than", or "equal to" other, respectively. ^ Technically, because Comparable is generic, implementers can define comparison against any other class, not just itself. In practice, however, T is almost always the same as the implementing class, e.g. MyClass implements Comparable<MyClass>.
Eric McIntyre
Eric McIntyre5mo ago
The Comparator<T> interface provides a compare(T a, T b) method, which has similar semantics to Comparable.compareTo(other). However, Comparator provides a mechanism for performing "external" comparisons on objects -- comparison semantics that are not intrinsic to the class itself. For instance, a Comparator<LocalDate> could be implemented that compares LocalDate objects based only on their month & year:
public class MyDateComparator implements Comparator<LocalDate> {
public int compare(LocalDate a, LocalDate b) {
if (a.getYear() == b.getYear()) {
return a.getMonthValue() - b.getMonthValue();
} else {
return a.getYear() - b.getYear();
}
}
}
public class MyDateComparator implements Comparator<LocalDate> {
public int compare(LocalDate a, LocalDate b) {
if (a.getYear() == b.getYear()) {
return a.getMonthValue() - b.getMonthValue();
} else {
return a.getYear() - b.getYear();
}
}
}
Comparators are heavily used within Java Collections to provide sorting logic to the collection implementations, such as to Collections.sort. They are also a functional interface, and very often implemented as lambdas.
⭐ Submission from dangerously_casual
Eric McIntyre
Eric McIntyre4w ago
The Object class provides an equals(Object) method that can be used to test for equality. To do that, one can override that method and write code for equality checks. If two objects are considered equal, firstObject.equals(secondObject) should return true, else it should return false. When overriding equals, one should make sure that a.equals(b) gives the same result as b.equals(a) (assuming that neither a nor b are null) and always also override hashCode and make sure that the hashCode() result is the same for all objects a and b where a.equals(b) is true.
public final class SomeClass{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}
}
public final class SomeClass{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}
}
SomeClass instance = new SomeClass("Hi", 1337);
System.out.println(instance.equals(new SomeClass("Hi", 1337)));//true
System.out.println(instance.equals(new SomeClass("Hi", 1338)));//false
System.out.println(instance.equals(new SomeClass("Ho", 1337)));//false
SomeClass instance = new SomeClass("Hi", 1337);
System.out.println(instance.equals(new SomeClass("Hi", 1337)));//true
System.out.println(instance.equals(new SomeClass("Hi", 1338)));//false
System.out.println(instance.equals(new SomeClass("Ho", 1337)));//false
The methods equals(Object) and hashCode() are used by many classes in the JDK for comparing objects, e.g. HashMap. Sometimes, it's also necessary to define some sort of order between objects. This can be done using the Comparable interface. A class can mark itself to be comparable to another class by implementing that interface and overriding the compareTo method. If firstObject and secondObject are equal (by the equals(Object) method), firstObject.compareTo(secondObject) as well as secondObject.compareTo(firstObject) should return 0. If firstObject is considered to be greater than secondObject, then firstObject.compareTo(secondObject) should return a value greater than 0 and secondObject.compareTo(firstObject) should return a value smaller than 0.
public final class SomeClass implements Comparable<SomeClass>{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}

@Override
public int compareTo(SomeClass other){
Objects.requireNonNull(other);
int someStringResult = someString.compareTo(other.someString);
if(someStringResult != 0){
return someStringResult;
}
return Integer.compare(someInt, other.someInt);
}
}
public final class SomeClass implements Comparable<SomeClass>{
private String someString;
private int someInt;

public SomeClass(String someString, int someInt) {
this.someString = someString;
this.someInt = someInt;
}

@Override
public boolean equals(Object o){
return o instanceof SomeClass other &&
Objects.equals(someString, other.someString) &&
someInt == other.someInt;
}
@Override
public int hashCode(){
return Objects.hash(someString, someInt);
}

@Override
public int compareTo(SomeClass other){
Objects.requireNonNull(other);
int someStringResult = someString.compareTo(other.someString);
if(someStringResult != 0){
return someStringResult;
}
return Integer.compare(someInt, other.someInt);
}
}
Want results from more Discord servers?
Add your server