Sorting in collection with comparator java

Java Collections sort()

Learn to use Collections.sort() method to sort a list of objects using some examples.

By default, the sort() method sorts a given list into ascending order (or natural order). We can use Collections.reverseOrder() method, which returns a Comparator, for reverse sorting.

1. Sorting in Natural Order and Reverse Order

Collections.sort(list); //Sorts in natural order Collections.sort(list, Collections.reverseOrder()); //Sorts in reverse order
  1. Above method sorts the specified list of items into their natural order.
  2. All items must implement the Comparable interface.
  3. All items must be mutually comparable and should not throw ClassCastException .
  4. This sort is guaranteed to be stable. It means that equal elements will not be reordered as a result of the sort.
  5. The specified list must be modifiable, but need not to be resizable.
  6. The sort() does not return any value.

1.1. Sorting an ArrayList of Strings

Java program to sort a list of strings lexicographically (in the dictionary order).

List names = Arrays.asList("Alex", "Charles", "Brian", "David"); //Prints - [Alex, Brian, Charles, David] Collections.sort(names); //Prints - [David, Charles, Brian, Alex] Collections.sort(names, Collections.reverseOrder()); 

1.2. Sorting ArrayList of Objects by Field

We may require to sort a list of custom objects which can have their own sorting logic. In this case, implement the Comparator interface in the custom class.

For example, the domain object Employee has default sorting on the name field. Checkout for comparison logic in compareTo() method.

public class Employee implements Comparable < private Integer id; private String name; private String email; private LocalDate dateOfBirth; //Getters and Setters @Override public int compareTo(Employee e) < return this.getName().compareTo(e.getName()); >>

Nest Java program sorts the list of Employee objects by their name;

ArrayList employees = methodReturnsUnsortedList(); //Narutal order sorting Collections.sort(employees); //Reverse sorting Collections.sort(employees, Collections.reverseOrder());

2. Custom Sorting using Comparators

The second parameter in sort() method takes an instance of Comparator .

We can implement any kind of comparison logic with the help of comparators and then we can use sort() method to sort the list based on the given custom logic.

Collections.sort(List, Comparator);

We can create a separate Comparator instances for each kind of sorting need, and then we can combine those instances to create group sorting effect.

For example, if we want to sort the Employee list on three fields – id, name, and age. In this case, we need to create 3 Comparator instances.

2.1. Creating Custom Comparator

This is general syntax to create a Comparator in Java. In this case, we are creating a Comparator which will sort the Employee list by id field.

Comparator compareById = new Comparator() < @Override public int compare(Employee o1, Employee o2) < return o1.getId().compareTo(o2.getId()); >>; Comparator compareByName = new Comparator() < @Override public int compare(Employee o1, Employee o2) < return o1.getName().compareTo(o2.getName()); >>;

We can use lambda expression for further shortening the syntax.

//Id Comparator Comparator compareById = (Employee o1, Employee o2) -> o1.getId().compareTo( o2.getId() ); //Name Comparator Comparator compareByName = (Employee o1, Employee o2) -> o1.getName().compareTo( o2.getName() );

2.2. Using Comparator for Sorting

ArrayList employees = getUnsortedEmployeeList(); Comparator compareById = (Employee o1, Employee o2) -> o1.getId().compareTo( o2.getId() ); Collections.sort(employees, compareById); Collections.sort(employees, compareById.reversed());

In the above code examples, we learned to sort an ArrayList in default order or reverse order.

We also learned to use the Comparators for implementing the custom sorting logic.

Источник

Comparator, сортировка коллекций

Comparator, сортировка коллекций - 1

— Сегодня будет небольшая, но интересная и полезная тема – сортировки коллекций.

— Сортировка? Я что-то про это слышал.

— Давным-давно каждый программист обязан был уметь писать сортировку. Умел и писал. Но те времена канули в лету. Сегодня написание своей сортировки считается дурным тоном, как и написание всего, что уже было придумано.

В Java (да и других языках программирования) сортировки уже реализованы. Твоя задача – научиться правильно пользоваться тем, что есть.

— У вспомогательного класса Collections есть статический метод sort, который используется для сортировки коллекций, а если точнее – списков. Элементы в коллекциях Map и Set не имеют порядка/номера, значит, и сортировать там нечего.

— Да, я вспомнил, я когда-то уже использовал этот метод для сортировки списка чисел.

— Отлично. Но этот метод гораздо мощнее чем, кажется на первый взгляд. Он может сортировать не только числа, но и любые объекты, по любым критериям. И помогают ему в этом два интерфейса: Comparable и Comparator.

Иногда бывает нужно отсортировать объекты, а не числа. Например, у тебя есть список людей, и ты хочешь отсортировать их по возрасту. Для этого есть интерфейс Comparable.

Давай я сначала покажу тебе пример, и все станет понятнее:

public class Woman implements Comparable < public int age; public Woman(int age) < this.age = age; >public int compareTo(Woman o) < return this.age - o.age; >>
public static void main(String[] args ) < ArrayListwomen = new ArrayList(); women.add(new Woman(18)); women.add(new Woman(21)); women.add(new Woman(5)); Collections.sort(women); >

Чтобы объекты можно было сортировать, сначала нужно научиться их сравнивать. Для этого и используется Comparable. Интерфейс Comparable является generic’ом – т.е. типом с параметром. У него всего один generic-метод – compareTo(T o). В этом методе и происходит сравнение переданного объекта (o) и текущего (this). Т.е. надо переопределить этот метод в своем классе и сравнить в нем текущий объект (this) с переданным.

— А как работает compareTo? Я думал, что он будет возвращать true/false в зависимости от того – больше переданный объект или меньше.

— Тут все немного хитрее. Метод compareTo возвращает не true/false, а значение типа int. На самом деле так сделано для простоты.

Когда компьютеру нужно определить больше ли одно число, чем другое, он просто вычитает из первого числа второе, а потом смотрит, что получилось. Если 0 – числа равны, если получилось число меньше нуля, то второе число больше, а если результат больше нуля, то больше уже первое число.

Тут используется та же логика. Согласно спецификации метод compareTo должен вернуть ноль, если сравниваемые объекты равны. Если метод compareTo вернул число больше нуля, это значит, что наш (this) объект больше, чем переданный. Если метод compareTo вернул число меньше нуля, то объект this меньше чем переданный.

— Да, но если ты сравниваешь объекты просто по какому-то параметру-числу, то можешь просто вернуть разницу между ними – вычесть один из другого. Как это и сделано в примере выше.

public int compareTo(Woman o)

— Вроде все понятно. Хотя может и не все. Но почти все.

— Отлично. Теперь рассмотрим более практическую задачу. Ты написал крутой сайт по пошиву женской одежды в Китае. Для описания своих пользователей ты используешь класс Woman. Ты даже сделал страницу с таблицей, где можешь посмотреть их всех. Но есть проблема…

Объект Woman содержит у тебя не только возраст, а еще целую кучу данных: имя, фамилию, рост, вес, количество детей, …

В таблице пользователей есть много колонок, и тут встает вопрос: а как сортировать пользователей по разным критериям? По весу, по возрасту, по фамилии?

— Гм. Действительно, часто вижу таблицы с сортировкой колонок. И как это сделать?

— А для этого есть второй интерфейс, о котором я хотел тебе сегодня рассказать – это интерфейс Comparator. И у него тоже есть метод сравнения, только он называется compare и принимает не один параметр, а два: int compare(T o1, T o2). Вот как это работает:

public static void main(String[] args ) < ArrayListwomen = new ArrayList(); women.add(new Woman(18, 0, 45, 170, "Ann")); women.add(new Woman(21, 1, 57, 168, "Iren")); women.add(new Woman(5, 0, 20, 110, "Angelina")); … Comparator compareByHeight = new Comparator() < public int compare(Woman o1, Woman o2) return o1.height - o2.height; > >; Collections.sort(women, compareByHeight); >

При использовании интерфейса Comparator, логика сравнения пары объектов не прячется внутрь класса/объекта, а реализуется в отдельном классе.

— Т.е. я могу сделать несколько классов, реализующих интерфейс Comparator, но в каждом из них сравнивать разные параметры? В одном – weight, в другом – age, в третьем – height?

— Да, это очень просто и удобно.

Мы просто вызываем метод Collections.sort, передаем туда список объектов и еще специальный объект во втором параметре, который реализует интерфейс Comparator и говорит, как правильно сравнивать пары объектов в процессе сортировки.

— Гм. Вроде все понятно. Дай-ка я сам попробую. Допустим, мне нужно отсортировать пользователей по весу, это будет так:

Comparator compareByWeight = new Comparator() < public int compare(Woman o1, Woman o2) < return o1.weight - o2.weight; >>; Collections.sort(women, compareByWeight);

— Отлично. А если я хочу отсортировать в обратном порядке?

— А подумать? Ответ очень простой!

return o1.weight - o2.weight;
return o2.weight – o1.weight;

— А если я хочу сортировать по фамилии? Как сортировать строки, Билаабо?

— А у строк уже реализован метод compareTo, надо просто вызвать его:

Comparator compareByName = new Comparator() < public int compare(Woman o1, Woman o2) < return o1.name.compareTo(o2.name); > >; Collections.sort(women, compareByName);

— Это был отличный урок, Билаабо, спасибо тебе большое.

Источник

Читайте также:  Свойства объекта event javascript
Оцените статью