3

Lets take an example you have two employee object having same values as follows.

Employee employee1 = new Employee(1001, "Sam", 20000);
Employee employee2 = new Employee(1001, "Sam", 20000);
if(doCompareEmployees(employee1, employee2)){
    System.out.println("Both employee objects are same.");
}else{
    System.out.println("Both employee objects are not same.");
}

//Here is compare method using java 8.

private boolean doCompareEmployees(Employee employee1, Employee employee2) {
int returnValue = Comparator.comparing(Employee::getID)
    .thenComparing(Employee::getName)
    .thenComparing(Employee::getSalary)
    .compare(employee1, employee2);
    if (returnValue != 0){
        return false;
    }   
    return true;
}

I would like know about, is there any other better approach to compare objects in Java 8 ?

ZhekaKozlov
  • 36,558
  • 20
  • 126
  • 155
Sabarish.K
  • 109
  • 1
  • 2
  • 7
  • 4
    Unless you want a custom comparison based on specific fields, the preferred way would be to override equals (and hashcode to be consistent) in your Employee class and make rid of this `doCompareEmployees` method substitued by `employee1.equals(employee2)` instead. – Alexis C. Dec 05 '17 at 14:40
  • 2
    The standard option still is to add an appropriate `equals` method to `Employee`. If that’s not possible, the best approach for property-wise check also hasn’t changed: `return employee1.getID()==employee2.getID()) && employee1.getName().equals(employee2.getName()) && employee1.getSalary()==employee2.getSalary());` – Holger Dec 05 '17 at 15:27
  • 1
    Possible duplicate of https://stackoverflow.com/questions/472626/how-to-generically-compare-entire-java-beans – tkruse Dec 06 '17 at 02:16
  • There are many possible ways, some classes that implement Comparable by default have pre-built "natural order" that you can use, or if you need something specific you can use Comparator interface and define your own sorting method. – whatamidoingwithmylife Dec 06 '17 at 17:53

2 Answers2

4

If you do not want to define an ordering on your objects, normally you would not write a Comparator.

The typical way to define equality for a class, is to define both an equals() and a hashCode() method. To implement hashCode(), Objects.hash() can help (present since Java 7).

public int hashCode() {
    return Objects.hash(id, name, salary);
}

public boolean equals(Object o) {
    if (o == this) return true;
    if (o == null || o.getClass() != getClass()) return false;
    Employee e = (Employee) o;
    return id == e.id && salary == e.salary && Objects.equals(name, e.name);
}

Although lambda expressions allow to write very elegant code in some cases, they are not the best solution for each problem.

Hoopje
  • 12,677
  • 8
  • 34
  • 50
1

You can check this LambdaEquals utility. However, as a good habit, you should stick to the equals overriding for the best performance. Overriding the "equals" method could be faster than Comparator.comparing.

Below is the same example of override as Hoopje provided, just slightly differs.

In the Employee class override the equals method:

public class Employee {
.....
.....
@Override
public boolean equals(Object o) {
     if(super.equals(o)) {
         return true;
     }
    if(!(o instanceof Employee)) {
        return false
    }

    Employee otherEmployee = (Employee) o;

    return 
        id == otherEmplyee.getId &&
        name == otherEmplyee.getName() &&
        salary == otherEmplyee.getSalary;

}


//Use the equal method
if(emp1.equals(emp2) {
    //do something
}
Octtavius
  • 563
  • 8
  • 29
  • `super.equals(0)`??? – ZhekaKozlov Dec 06 '17 at 17:48
  • @ZhekaKozlov sorry, my bad. typo :) – Octtavius Dec 06 '17 at 17:51
  • I would change it to `this == o` – ZhekaKozlov Dec 06 '17 at 17:52
  • == compares reference, not values. you will get wrong result – Octtavius Dec 06 '17 at 18:01
  • 1
    In this case, `super.equals(o)` and `this == o` are equivalent, because `Employee`'s direct superclass is `Object` and `Object.equals()` is implemented in terms of `==`. However, typically you do not want to call `super.equals(o)` in the way you do. Suppose `Employee` is a subclass of `A` and inherits its `salary` field. Then `new Employee(1, "John", 10).equals(new Employee(2, "Mark", 10)) == true`, because both have the same salary and thus `A.equals(o)` would return true. – Hoopje Dec 06 '17 at 19:49