Обратная сортировка потока файлов через lambda в Java 8

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Для сортировки потока элементов в обратном порядке воспользуйтесь методом sorted() в сочетании с Comparator.reverseOrder():

Java
Скопировать код
List<String> descList = list.stream()
                            .sorted(Comparator.reverseOrder())
                            .collect(Collectors.toList());

Если требуется отсортировать объекты пользовательского типа или сортировать по определенному полю, используйте Comparator.comparing():

Java
Скопировать код
List<CustomType> descList = list.stream()
                                .sorted(Comparator.comparing(CustomType::getField).reversed())
                                .collect(Collectors.toList());

Если нужно отсортировать список файлов по дате последнего изменения, воспользуйтесь таким подходом:

Java
Скопировать код
List<File> sortedFiles = files.stream()
                              .sorted(Comparator.comparing(File::lastModified).reversed())
                              .collect(Collectors.toList());

Такой подход позволит переместить более ранние значения в конец списка, так как reversed() инвертирует порядок сортировки.

Кинга Идем в IT: пошаговый план для смены профессии

От лямбда-выражений до ссылок на методы

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

Java
Скопировать код
list.stream()
    .sorted(Comparator.comparing(MyClass::getValue).reversed())
    .forEach(System.out::println);

Здесь MyClass::getValue — это метод, значение которого используется для сортировки, а reversed() переворачивает порядок сортировки.

Изменение потока данных после сортировки

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

  • Фильтрация
Java
Скопировать код
list.stream()
    .sorted(Comparator.comparing(String::length).reversed())
    .filter(s -> s.startsWith("A"))
    .collect(Collectors.toList());
  • Пропуск и ограничение
Java
Скопировать код
list.stream()
    .sorted(Comparator.comparingInt(String::length).reversed())
    .skip(2)
    .limit(5)
    .collect(Collectors.toList());
  • Если требуется удалить элементы, сначала нужно получить результаты сортировки, а затем уже изменять собранные данные, чтобы не нарушать свойство неизменяемости потоков.

Сценарии сортировки, с которыми вы столкнетесь

Сложные сценарии сортировки встречаются довольно часто. Вот некоторые из них:

  • Сортировка по значениям вложенных атрибутов:
Java
Скопировать код
list.stream()
    .sorted(Comparator.comparing((CustomType t) -> t.getNestedType().getNestedField()).reversed())
    .collect(Collectors.toList());
  • Сортировка по нескольким полям:
Java
Скопировать код
list.stream()
    .sorted(Comparator.comparing(CustomType::getPrimaryField)
                      .thenComparing(CustomType::getSecondaryField).reversed())
    .collect(Collectors.toList());
  • Обработка null-значений:
Java
Скопировать код
list.stream()
    .sorted(Comparator.comparing(CustomType::getField, Comparator.nullsLast(Comparator.naturalOrder())).reversed())
    .collect(Collectors.toList());
  • Создание собственного компаратора для реализации особой логики сравнения:
Java
Скопировать код
list.stream()
    .sorted((o1, o2) -> {
        // здесь сложная логика
        return o2.compareTo(o1);
    })
    .collect(Collectors.toList());

Визуализация

Визуализируем процесс обратной сортировки на примере гонки автомобилей:

Обычный финиш: [4-е место 🚗, 3-е место 🛺, 2-е место 🏎, 1-е место 🚀] /// Первые приходят последними.

Применение Comparator.comparing().reversed() позволяет самым быстрым ускориться.

Обратная сортировка с использованием lambda: [1-е место 🚀, 2-е место 🏎, 3-е место 🛺, 4-е место 🚗]

Таким образом, лямбда-выражения в Java 8 меняют направление гонки на противоположное:

Java
Скопировать код
stream.sorted(Comparator.comparing(T::getSpeed).reversed())
// Самый быстрый оставил все за собой!

При работе со значениями, такими как временные метки, используйте методы Comparator, вместо умножения на -1:

Java
Скопировать код
list.stream()
    .sorted(Comparator.comparingLong(T::getTimestamp).reversed())
    .collect(Collectors.toList());

Отсортированные результаты можно собрать в коллекцию по своему выбору — список, множество, карту и т.д.

Полезные материалы

  1. Stream (Java Platform SE 8) — официальная документация API Java 8 для интерфейса Stream.
  2. Java 8 stream reverse order – Stack Overflow — вопросы и ответы, касающиеся сортировки потоков в обратном порядке.
  3. Туториал по Java 8 Stream – winterbe — детальное руководство по использованию потоков в Java 8 с примерами.
  4. Однострочники в Java 8 с помощью лямбд — примеры эффективного использования лямбда-выражений в Java 8 для написания компактного кода.