Рубрики
Без рубрики

Сопоставимый и компаратор в примере Java

Сопоставимые и компараторы в Java используются для сортировки коллекции или массива объектов java. Сопоставимые и сопоставимые примеры программ для сортировки списка java.

Автор оригинала: Pankaj Kumar.

Сопоставимый и компаратор в Java очень полезны для сортировки коллекции объектов. Java предоставляет некоторые встроенные методы для сортировки массива примитивных типов или массива классов-оболочек или списка. Здесь мы сначала узнаем, как мы можем сортировать массив/список примитивных типов и классов-оболочек, а затем мы будем использовать java.lang.Сопоставимые и java.util.Компаратор интерфейсы для сортировки массива/списка пользовательских классов.

Давайте посмотрим, как мы можем сортировать примитивные типы или массив объектов и список с помощью простой программы.

package com.journaldev.sort;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;

public class JavaObjectSorting {

    /**
     * This class shows how to sort primitive arrays, 
     * Wrapper classes Object Arrays
     * @param args
     */
    public static void main(String[] args) {
        //sort primitives array like int array
        int[] intArr = {5,9,1,10};
        Arrays.sort(intArr);
        System.out.println(Arrays.toString(intArr));
        
        //sorting String array
        String[] strArr = {"A", "C", "B", "Z", "E"};
        Arrays.sort(strArr);
        System.out.println(Arrays.toString(strArr));
        
        //sorting list of objects of Wrapper classes
        List strList = new ArrayList();
        strList.add("A");
        strList.add("C");
        strList.add("B");
        strList.add("Z");
        strList.add("E");
        Collections.sort(strList);
        for(String str: strList) System.out.print(" "+str);
    }
}

Результатом работы вышеуказанной программы является:

[1, 5, 9, 10]
[A, B, C, E, Z]
 A B C E Z

Теперь давайте попробуем отсортировать массив объектов.

package com.journaldev.sort;

public class Employee {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    //this is overridden to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Вот код, который я использовал для сортировки массива объектов сотрудников.

//sorting object array
Employee[] empArr = new Employee[4];
empArr[0] = new Employee(10, "Mikey", 25, 10000);
empArr[1] = new Employee(20, "Arun", 29, 20000);
empArr[2] = new Employee(5, "Lisa", 35, 5000);
empArr[3] = new Employee(1, "Pankaj", 32, 50000);

//sorting employees array using Comparable interface implementation
Arrays.sort(empArr);
System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));

Когда я попытался запустить это, оно вызывает следующее исключение во время выполнения.

Exception in thread "main" java.lang.ClassCastException: com.journaldev.sort.Employee cannot be cast to java.lang.Comparable
	at java.util.ComparableTimSort.countRunAndMakeAscending(ComparableTimSort.java:290)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:157)
	at java.util.ComparableTimSort.sort(ComparableTimSort.java:146)
	at java.util.Arrays.sort(Arrays.java:472)
	at com.journaldev.sort.JavaSorting.main(JavaSorting.java:41)

Сопоставимый и компаратор

Java предоставляет Сопоставимый интерфейс, который должен быть реализован любым пользовательским классом, если мы хотим использовать Массивы или Коллекции методы сортировки.

Сопоставимый интерфейс имеет метод compareTo(T obj) , который используется методами сортировки, вы можете проверить любую оболочку, строку или класс даты, чтобы подтвердить это. Мы должны переопределить этот метод таким образом, чтобы он возвращал отрицательное целое число, ноль или положительное целое число, если “этот” объект меньше, равен или больше объекта, переданного в качестве аргумента.

После реализации сопоставимого интерфейса в классе сотрудников, вот полученный класс сотрудников.

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

}

Теперь, когда мы выполним приведенный выше фрагмент для сортировки массивов сотрудников и распечатаем его, вот результат.

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]

Как вы можете видеть, массив сотрудников отсортирован по идентификатору в порядке возрастания.

Но в большинстве реальных сценариев нам нужна сортировка по различным параметрам. Например, как генеральный директор, я хотел бы сортировать сотрудников по заработной плате, отдел кадров хотел бы сортировать их по возрасту. Это ситуация, когда нам нужно использовать Java-компаратор интерфейс, потому что Comparable.compareTo(объект o) реализация метода может обеспечить сортировку по умолчанию, и мы не можем изменять ее динамически. В то время как с помощью Comparator мы можем определить несколько методов с различными способами сортировки, а затем выбрать метод сортировки в соответствии с нашими требованиями.

Java-компаратор

Интерфейс компаратора сравнение(объект o1, объект o2) необходимо реализовать метод, который принимает два аргумента объекта, он должен быть реализован таким образом, чтобы он возвращал отрицательное значение int, если первый аргумент меньше второго, и возвращал ноль, если они равны, и положительное значение int, если первый аргумент больше второго.

Интерфейсы Comparable и Comparator используют универсальные средства для проверки типов во время компиляции, узнайте больше о универсальных средствах Java .

Вот как мы можем создать другую реализацию компаратора в классе Employee.

/**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator SalaryComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator AgeComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator NameComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };

Все вышеперечисленные реализации интерфейса компаратора являются анонимными классами .

Мы можем использовать эти компараторы для передачи аргумента функции сортировки классов массивов и коллекций.

//sort employees array using Comparator by Salary
Arrays.sort(empArr, Employee.SalaryComparator);
System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Age
Arrays.sort(empArr, Employee.AgeComparator);
System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));

//sort employees array using Comparator by Name
Arrays.sort(empArr, Employee.NameComparator);
System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));

Вот вывод приведенного выше фрагмента кода:

Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]

Итак, теперь мы знаем, что если мы хотим отсортировать массив или список объектов java, нам необходимо реализовать сопоставимый интерфейс java для обеспечения сортировки по умолчанию, и мы должны реализовать интерфейс java Comparator для обеспечения различных способов сортировки.

Мы также можем создать отдельный класс, реализующий интерфейс Comparator , а затем использовать его.

Вот заключительные классы, которые мы объяснили Comparable и Comparator на Java.

package com.journaldev.sort;

import java.util.Comparator;

public class Employee implements Comparable {

    private int id;
    private String name;
    private int age;
    private long salary;

    public int getId() {
        return id;
    }

    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public long getSalary() {
        return salary;
    }

    public Employee(int id, String name, int age, int salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public int compareTo(Employee emp) {
        //let's sort the employee based on an id in ascending order
        //returns a negative integer, zero, or a positive integer as this employee id
        //is less than, equal to, or greater than the specified object.
        return (this.id - emp.id);
    }

    @Override
    //this is required to print the user-friendly information about the Employee
    public String toString() {
        return "[id=" + this.id + ", name=" + this.name + ", age=" + this.age + ", salary=" +
                this.salary + "]";
    }

    /**
     * Comparator to sort employees list or array in order of Salary
     */
    public static Comparator SalaryComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return (int) (e1.getSalary() - e2.getSalary());
        }
    };

    /**
     * Comparator to sort employees list or array in order of Age
     */
    public static Comparator AgeComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getAge() - e2.getAge();
        }
    };

    /**
     * Comparator to sort employees list or array in order of Name
     */
    public static Comparator NameComparator = new Comparator() {

        @Override
        public int compare(Employee e1, Employee e2) {
            return e1.getName().compareTo(e2.getName());
        }
    };
}

Вот реализация отдельного класса интерфейса Comparator, которая будет сравнивать два объекта сотрудников сначала по их идентификатору, а если они совпадают, то по имени.

package com.journaldev.sort;

import java.util.Comparator;

public class EmployeeComparatorByIdAndName implements Comparator {

    @Override
    public int compare(Employee o1, Employee o2) {
        int flag = o1.getId() - o2.getId();
        if(flag==0) flag = o1.getName().compareTo(o2.getName());
        return flag;
    }

}

Вот тестовый класс, в котором мы используем различные способы сортировки объектов в java с использованием Comparable и Comparator.

package com.journaldev.sort;

import java.util.Arrays;

public class JavaObjectSorting {

    /**
     * This class shows how to sort custom objects array/list
     * implementing Comparable and Comparator interfaces
     * @param args
     */
    public static void main(String[] args) {

        //sorting custom object array
        Employee[] empArr = new Employee[4];
        empArr[0] = new Employee(10, "Mikey", 25, 10000);
        empArr[1] = new Employee(20, "Arun", 29, 20000);
        empArr[2] = new Employee(5, "Lisa", 35, 5000);
        empArr[3] = new Employee(1, "Pankaj", 32, 50000);
        
        //sorting employees array using Comparable interface implementation
        Arrays.sort(empArr);
        System.out.println("Default Sorting of Employees list:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Salary
        Arrays.sort(empArr, Employee.SalaryComparator);
        System.out.println("Employees list sorted by Salary:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Age
        Arrays.sort(empArr, Employee.AgeComparator);
        System.out.println("Employees list sorted by Age:\n"+Arrays.toString(empArr));
        
        //sort employees array using Comparator by Name
        Arrays.sort(empArr, Employee.NameComparator);
        System.out.println("Employees list sorted by Name:\n"+Arrays.toString(empArr));
        
        //Employees list sorted by ID and then name using Comparator class
        empArr[0] = new Employee(1, "Mikey", 25, 10000);
        Arrays.sort(empArr, new EmployeeComparatorByIdAndName());
        System.out.println("Employees list sorted by ID and Name:\n"+Arrays.toString(empArr));
    }

}

Вот результат работы вышеприведенной программы:

Default Sorting of Employees list:
[[id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000]]
Employees list sorted by Salary:
[[id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by Age:
[[id=10, name=Mikey, age=25, salary=10000], [id=20, name=Arun, age=29, salary=20000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000]]
Employees list sorted by Name:
[[id=20, name=Arun, age=29, salary=20000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000]]
Employees list sorted by ID and Name:
[[id=1, name=Mikey, age=25, salary=10000], [id=1, name=Pankaj, age=32, salary=50000], [id=5, name=Lisa, age=35, salary=5000], [id=10, name=Mikey, age=25, salary=10000]]

java.lang.Сопоставимые и java.util.Comparator – это мощные интерфейсы, которые можно использовать для обеспечения сортировки объектов в java.

Сопоставимый против компаратора

  1. Сопоставимый интерфейс может использоваться для обеспечения единого способа сортировки, в то время как интерфейс компаратора используется для обеспечения различных способов сортировки.
  2. Для использования Comparable класс должен реализовать его, тогда как для использования Comparator нам не нужно вносить какие-либо изменения в класс.
  3. Сопоставимый интерфейс находится в java.lang пакете, тогда как интерфейс компаратора присутствует в java.util пакете.
  4. Нам не нужно вносить какие-либо изменения в код на стороне клиента для использования сопоставимых методов Arrays.sort() или Collection.sort() автоматически использует метод compareTo() класса. Для компаратора клиенту необходимо предоставить класс компаратора для использования в методе compare ().

Знаете ли вы, что метод Collections.sort (), принимающий аргумент Компаратора, следует шаблону стратегии ?