Сортировка списка объектов по полю в Java

Java предоставляет несколько способов сортировки списка. В этой статье мы покажем, как отсортировать список объектов по полю.

Список объектов

В наших примерах мы будем использовать следующий User класс:

package com.example.demo; 
import java.util.Date; 
public class User { 
  private long id; 
  private String email; 
  private Date createdOn; 
  // other getters and setters omitted 
  public Date getCreatedOn() { 
    return createdOn; 
  } 
  public void setCreatedOn(Date createdOn) { 
    this.createdOn = createdOn; 
  } 
}

Предположим, у нас есть служебный метод, который возвращает список всех пользователей:

List<User> users = userService.getAllUsers();

Сортировать список объектов по полю

Итак, у нас есть список пользователей, и мы хотим отсортировать их по createdDate.

Давайте рассмотрим несколько различных подходов и рассмотрим преимущества и недостатки каждого из них.

Вариант 1: Collections.sort () с Comparable

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

Для этого требуется реализовать метод compareTo (), как показано в строках 20–26 ниже:

package com.example.demo; 
import java.util.Date; 
public class User implements Comparable<User> { 
  private long id; 
  private String email; 
  private Date createdOn; 
  // other getters and setters omitted 
  public Date getCreatedOn() { 
    return createdOn; } 
  public void setCreatedOn(Date createdOn) { 
    this.createdOn = createdOn; } 
  @Override public int compareTo(User u) { 
    if (getCreatedOn() == null || u.getCreatedOn() == null) { 
      return 0; 
    } 
    return getCreatedOn().compareTo(u.getCreatedOn());
  } 
}

Теперь мы можем вызвать Collections.sort () для выполнения сортировки.

Сортировать по дате создания по возрастанию

Collections.sort(users);

Сортировать по дате создания по убыванию

Collections.sort(users); 
Collections.reverse(users);

Этот параметр требует изменения нашего класса и определения порядка сортировки по умолчанию (или естественного). Для сортировки в порядке убывания требуется два отдельных вызова методов.

Этот вариант не позволяет выполнять сортировку по другому полю, кроме того, которое мы выбрали.

Вариант 2: Collections.sort () с компаратором

Вместо того, чтобы изменять наш класс, мы можем передать компаратор в Collections.sort (). В приведенных ниже примерах создается компаратор с использованием анонимного класса.

Сортировать по дате создания по возрастанию

Collections.sort(users, new Comparator<User>() { 
  @Override public int compare(User u1, User u2) { 
    return u1.getCreatedOn().compareTo(u2.getCreatedOn()); 
} });

Сортировать по дате создания по убыванию

Мы меняем местами u1 и u2, чтобы поменять местами порядок сортировки.

Collections.sort(users, new Comparator<User>() { 
  @Override public int compare(User u1, User u2) { 
    return u2.getCreatedOn().compareTo(u1.getCreatedOn()); 
} });

Этот параметр позволяет коду вне класса определять критерии и порядок сортировки.

Однако для этого требуется уродливый анонимный класс, который не очень читается.

Вариант 3: сортировка интерфейса списка () [Java 8]

Java 8 представила метод сортировки в интерфейсе List, который может использовать компаратор.

Метод Comparator.comparing () принимает ссылку на метод, которая служит основой для сравнения. Итак, мы передаем User :: getCreatedOn для сортировки по полю createdOn.

Сортировать по дате создания по возрастанию

users.sort(Comparator.comparing(User::getCreatedOn));

Сортировать по дате создания по убыванию

users.sort(Comparator.comparing(User::getCreatedOn).reversed());

Как видим, код становится намного проще и удобнее для чтения.

Вариант 4. Интерфейс потока sorted () [Java 8]

Предположим, мы не хотим изменять исходный список, а возвращаем новый отсортированный список.

В этой ситуации мы можем использовать метод sorted () из интерфейса Stream, представленного в Java 8.

Вернуть новый список, отсортированный по дате создания по возрастанию

List<User> sortedUsers = users.stream()   
  .sorted(Comparator.comparing(User::getCreatedOn))      
  .collect(Collectors.toList());

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

List<User> sortedUsers = users.stream() 
  .sorted(Comparator.comparing(User::getCreatedOn).reversed())   
  .collect(Collectors.toList());

Вывод

Хотя каждый из обсуждаемых параметров выполняет сортировку, рекомендуется использовать последние два параметра, поскольку их легче кодировать, отлаживать и читать.

Первоначально опубликовано на www.codebyamir.com 9 мая 2018 г.