Skip to content
Related Articles
Open in App
Not now

Related Articles

Why to Use Comparator Interface Rather than Comparable Interface in Java?

Improve Article
Save Article
  • Last Updated : 15 Nov, 2022
Improve Article
Save Article

Prerequisite: Comparable vs Comparator in Java

Throughout the entire lifecycle of the project, we will be creating multiple classes in Java according to our requirements, and sorting is much required in many situations, especially during the report generation, we need to display the data according to the sorted order either in ascending/descending order. Even report generation requires not only single-field sorted order but also multiple fields and also multi-variant sort mechanism is also needed. In that case, we need to depend on Java Comparator Interface which is available in java.util package. Let us take a sample maven java project containing JUnit dependency to look at this feature and justify whether the sorting happens according to our needs or not by using JUnit.

Example Maven Project

Project Structure:

Project Structure

 

This is the maven project containing JUNIT dependencies in

pom.xml

XML




<?xml version="1.0" encoding="UTF-8"?>
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
                             http://maven.apache.org/xsd/maven-4.0.0.xsd">
  
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.gfg.ComparatorServicesInJava</groupId>
    <artifactId>ComparatorServicesInJava</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
  
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
        <junit.version>5.3.1</junit.version>
        <pitest.version>1.4.3</pitest.version>
    </properties>
  
    <dependencies>
  
        <!-- junit 5, unit test -->
        <dependency>
            <groupId>org.junit.jupiter</groupId>
            <artifactId>junit-jupiter-engine</artifactId>
            <version>${junit.version}</version>
            <scope>test</scope>
        </dependency>
  
    </dependencies>
    <build>
        <finalName>maven-mutation-testing</finalName>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-surefire-plugin</artifactId>
                <version>3.0.0-M1</version>
            </plugin>
  
            <plugin>
                <groupId>org.pitest</groupId>
                <artifactId>pitest-maven</artifactId>
                <version>${pitest.version}</version>
  
                <executions>
                    <execution>
                        <id>pit-report</id>
                        <phase>test</phase>
                        <goals>
                            <goal>mutationCoverage</goal>
                        </goals>
                    </execution>
                </executions>
  
                <!-- https://github.com/hcoles/pitest/issues/284 -->
                <!-- Need this to support JUnit 5 -->
                <dependencies>
                    <dependency>
                        <groupId>org.pitest</groupId>
                        <artifactId>pitest-junit5-plugin</artifactId>
                        <version>0.8</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <targetClasses>
                        <param>com.gfg.ComparatorServicesInJava.*ComparatorServicesInJava*</param>
                    </targetClasses>
                    <targetTests>
                        <param>com.gfg.ComparatorServicesInJava.*</param>
                    </targetTests>
                </configuration>
            </plugin>
  
        </plugins>
    </build>
  
</project>

Let’s start with the bean class that contains comparisons i.e. sort by  in separate  classes and each class implements a comparator as well specific to

  • Companyname
  • Salary
  • Designation
  • Designation and Salary

Recruitment.java

Java




import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
  
public class Recruitment {
    public Recruitment(String companyName, String employeeName, String designation, double salary,boolean status) {
        super();
        this.companyName = companyName;
        this.employeeName = employeeName;
        this.designation = designation;
        this.salary = salary;
        this.status = status;
    }
  
    public Recruitment() {
        // via setter methods, rest fields are done
    }
  
    String companyName;
    String designation;
    String employeeName;
    double salary;
    boolean status;    
  
    public String getCompanyName() {
        return companyName;
    }
  
    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }
  
    public String getDesignation() {
        return designation;
    }
  
    public void setDesignation(String designation) {
        this.designation = designation;
    }
  
    public String getEmployeeName() {
        return employeeName;
    }
  
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
  
    public double getSalary() {
        return salary;
    }
  
    public void setSalary(double salary) {
        this.salary = salary;
    }
  
    public boolean isStatus() {
        return status;
    }
  
    public void setStatus(boolean status) {
        this.status = status;
    }
  
    // Method of Recruitment class
    // To print Recruitment details in main()
    public String toString()
    {
   
        // Returning attributes of Recruitment
        return this.companyName + " " + this.employeeName + " "
            + this.designation + " " + this.salary + " " + this.status;
    }
      
    public static void main(String args[]) {
        // Creating an empty ArrayList of Student type
        ArrayList<Recruitment> list = new ArrayList<Recruitment>();
   
        // Adding entries in above List
        // using add() method
        list.add(new Recruitment("abc consultants","Rachel","Analyst",100000.0,true));
        list.add(new Recruitment("nyc consultants","Monica","DBA",90000.0,true));
        list.add(new Recruitment("abc consultants","Phoebe","Programmer",70000.0,true));
        list.add(new Recruitment("nj consultants","Jane","Programmer",80000.0,false));
          
        list.add(new Recruitment("xyz consultants","Ross","ProgramManager",200000.0,true));
        list.add(new Recruitment("chennai consultants","Chandler","ProjectManager",150000.0,true));
        list.add(new Recruitment("xyz consultants","Joe","Programmer",80000.0,true));
        list.add(new Recruitment("mumbai consultants","Any","Programmer",85000.0,false));        
   
        // Display message on console for better readability
        System.out.println("Unsorted order of the details");
   
        // Iterating over entries to print them
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
   
        // Sorting the entries by company name
        Collections.sort(list, new GetDataByCompanyName()); 
          
        System.out.println("\nSorted by CompanyName");
   
        // We will get the sorted order now by company name
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
   
        // Sorting the  entries by salary
        Collections.sort(list, new GetDataBySalary()); 
  
        System.out.println("\nSorted by salary");
   
        // We will get the sorted order now by salary
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
          
         // Sorting the  entries by designation
        Collections.sort(list, new GetDataByDesignation()); 
  
        System.out.println("\nSorted by designation");
   
        // We will get the sorted order now by designation
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
          
        // Sorting the  entries by designation and salary
        Collections.sort(list, new GetDataByDesignationAndSalary());
   
        System.out.println("\nSorted by designation and salary");
   
        // We will get the sorted order now by salary
        for (int i = 0; i < list.size(); i++)
            System.out.println(list.get(i));
      
    }
  
}
class GetDataByCompanyName implements Comparator<Recruitment>{
  
    @Override
    public int compare(Recruitment recruitment1, Recruitment recruitment2) {
        return recruitment1.companyName.compareTo(recruitment2.companyName);
    }
  
}
class GetDataBySalary implements Comparator<Recruitment> {
    @Override
    public int compare(Recruitment recruitment1, Recruitment recruitment2) {
        return (int) (recruitment1.salary - recruitment2.salary);
    }
  
}
class GetDataByDesignation implements Comparator<Recruitment> {
    @Override
    public int compare(Recruitment recruitment1, Recruitment recruitment2) {
        return recruitment1.designation.compareTo(recruitment2.designation);
    }
  
}
  
// Using 2 fields to compare
class GetDataByDesignationAndSalary implements Comparator<Recruitment> {
  
    @Override
    public int compare(Recruitment recruitment1, Recruitment recruitment2) {
        int designationComparision = recruitment1.designation.compareTo(recruitment2.designation);
        int salaryComparision = (int) (recruitment1.salary - recruitment2.salary);
        return (salaryComparision == 0) ? designationComparision
                : salaryComparision;
    }
      
}

As we are implementing java.util.comparator, not only the natural order of sorting, based on our requirements, we can sort based on different fields. Hence 4 different classes are introduced to produce the result. Not only on a single field but on more than 1 field also sorting is possible. These are the advantages of using a comparator. If needed, we can put some test data and check for the same in the console

 

Now let us see the testcases to justify the same.

TestComparatorServicesJava.java

Java




import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertTrue;
  
import java.util.ArrayList;
import java.util.Collections;
  
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
  
public class TestComparatorServicesJava {
    private void addListElements(ArrayList<Recruitment> list) {
        // Adding entries in above List
        // using add() method
        list.add(new Recruitment("abc consultants","Rachel","Analyst",100000.0,true));
        list.add(new Recruitment("nyc consultants","Monica","DBA",90000.0,true));
        list.add(new Recruitment("abc consultants","Phoebe","Programmer",70000.0,true));
        list.add(new Recruitment("nj consultants","Jane","Programmer",80000.0,false));
          
        list.add(new Recruitment("xyz consultants","Ross","ProgramManager",200000.0,true));
        list.add(new Recruitment("chennai consultants","Chandler","ProjectManager",150000.0,true));
        list.add(new Recruitment("xyz consultants","Joe","Programmer",80000.0,true));
        list.add(new Recruitment("mumbai consultants","Any","Programmer",85000.0,false));
    }
    
    @DisplayName("Test check whether sorting done by company name ")
    @Test
    public void testSortByCompanyName() {
        // Creating an empty ArrayList of Recruitment type
        ArrayList<Recruitment> list = new ArrayList<Recruitment>();
   
        addListElements(list);
          
        // Sorting the entries by company name
        Collections.sort(list, new GetDataByCompanyName());
            
        // Assert the data for sorting by company name
        assertEquals(true, list.get(0).getCompanyName().equalsIgnoreCase("abc consultants"));
        assertEquals(true, list.get(1).getEmployeeName().equalsIgnoreCase("Phoebe"));
        assertEquals(true, list.get(2).getDesignation().equalsIgnoreCase("ProjectManager"));
          
        assertTrue(list.get(0).getEmployeeName().equalsIgnoreCase("Rachel"));
        assertTrue(list.get(list.size()-1).getCompanyName().equalsIgnoreCase("xyz consultants"));
        assertTrue(list.get(list.size()-1).getDesignation().equalsIgnoreCase("Programmer"));
                  
    }
    
    @DisplayName("Test check whether sorting done by salary ")
    @Test
    public void testSortBySalary() {
        // Creating an empty ArrayList of Recruitment type
        ArrayList<Recruitment> list = new ArrayList<Recruitment>();
   
        addListElements(list);
          
        // Sorting the entries by company name
        Collections.sort(list, new GetDataBySalary());
            
        // Assert the data for sorting by company name
        assertEquals(true, list.get(0).getCompanyName().equalsIgnoreCase("abc consultants"));
        assertEquals(true, list.get(1).getCompanyName().equalsIgnoreCase("nj consultants"));
        assertEquals(true, list.get(2).getSalary() == 80000.0);
          
        assertTrue(list.get(0).getEmployeeName().equalsIgnoreCase("Phoebe"));
        assertTrue(list.get(list.size()-1).getCompanyName().equalsIgnoreCase("xyz consultants"));
        assertTrue(list.get(list.size()-1).getDesignation().equalsIgnoreCase("ProgramManager"));
        assertTrue(list.get(0).getSalary() == 70000.0);
        assertTrue(list.get(list.size()-1).getSalary() == 200000.0);
                  
    }
    
    @DisplayName("Test check whether sorting done by designation ")
    @Test
    public void testSortByDesignation() {
        // Creating an empty ArrayList of Recruitment type
        ArrayList<Recruitment> list = new ArrayList<Recruitment>();
   
        addListElements(list);
          
        // Sorting the entries by Designation
        Collections.sort(list, new GetDataByDesignation());
            
        // Assert the data for sorting by company name
        assertEquals(true, list.get(0).getCompanyName().equalsIgnoreCase("abc consultants"));
        assertEquals(true, list.get(1).getCompanyName().equalsIgnoreCase("nyc consultants"));
        assertEquals(true, list.get(2).getSalary() == 200000.0);
          
        assertTrue(list.get(0).getEmployeeName().equalsIgnoreCase("Rachel"));
        assertTrue(list.get(list.size()-1).getCompanyName().equalsIgnoreCase("chennai consultants"));
        assertTrue(list.get(list.size()-1).getDesignation().equalsIgnoreCase("ProjectManager"));
        assertTrue(list.get(0).getSalary() == 100000.0);
        assertTrue(list.get(list.size()-1).getSalary() == 150000.0);
                  
    }
      
    @DisplayName("Test check whether sorting done both designation and salary ")
    @Test
    public void testSortByBothDesignationAndSalary() {
        // Creating an empty ArrayList of Recruitment type
        ArrayList<Recruitment> list = new ArrayList<Recruitment>();
   
        addListElements(list);
          
        // Sorting the entries by designation and salary
        Collections.sort(list, new GetDataByDesignationAndSalary());
            
        // Assert the data for sorting by designation and salary
        assertEquals(true, list.get(0).getCompanyName().equalsIgnoreCase("abc consultants"));
        assertEquals(true, list.get(1).getCompanyName().equalsIgnoreCase("nj consultants"));
        assertEquals(true, list.get(2).getSalary() == 80000.0);
          
        assertTrue(list.get(0).getEmployeeName().equalsIgnoreCase("Phoebe"));
        assertTrue(list.get(list.size()-2).getCompanyName().equalsIgnoreCase("chennai consultants"));
        assertTrue(list.get(list.size()-2).getDesignation().equalsIgnoreCase("ProjectManager"));
        assertTrue(list.get(3).getSalary() == 85000.0);
        assertTrue(list.get(list.size()-1).getSalary() == 200000.0);
        assertTrue(list.get(list.size()-1).getDesignation().equalsIgnoreCase("ProgramManager"));
    }
}

Let us see the output and from here we can understand that comparisons can be done on any field and even on more than one field.

 


My Personal Notes arrow_drop_up
Related Articles

Start Your Coding Journey Now!