Сортировка списков – один из ярких примеров использования лямбда-функций и их преимущества перед другими способами. Лямбда-функции позволяют спрятать процесс перебора элементов внутрь метода сортировки, оставив программисту задачу реализации способа сравнения двух элементов. В этом уроке мы научимся сортировать списки по произвольным условиям, используя метод sort()
списков.
Обычная сортировка списка в естественном порядке сводится к вызову одного метода:
var langs = new ArrayList<>(List.of("ruby", "php", "python", "javascript"));
Collections.sort(langs); // [javascript, php, python, ruby]
Предположим, что мы хотим выполнить сортировку на основе длины слов в порядке возрастания. Что нам делать в этом случае? Без использования лямбда-функций у нас есть два варианта:
- Реализовать сортировку самостоятельно. Самый дорогой способ, так как требует постоянно реализовывать заново один и тот же алгоритм сортировки.
- Воспользоваться механизмом Comparator, который позволяет создать отдельный класс с логикой сортировки. Объект этого класса будет использоваться во время сортировки для сравнения элементов. Лучше, чем первый способ, но все еще очень многословный.
Лямбда-функции позволяют отделить алгоритм сортировки от логики сравнения элементов, как во втором варианте, но сама реализации логики сравнения значительно упрощается, так как вместо создания целого класса, достаточно описать лямбда-функцию, прямо во время сортировки.
langs.sort((v1, v2) -> Integer.compare(v1.length(), v2.length()));
System.out.println(langs); // [php, ruby, python, javascript]
Лямбда-функция, передаваемая в метод sort()
, принимает на вход два элемента в том порядке, в котором они идут в исходном списке. Если элементы равны между собой, то функция должна вернуть 0, если первый элемент меньше чем второй, то -1, если второй меньше чем первый, то 1.
< | == | > |
---|---|---|
-1 | 0 | 1 |
В случае примитивных типов данных, такую логику не нужно реализовывать самостоятельно, она уже реализована в методах Character.compare()
, Integer.compare()
и так далее. В примере выше как раз используется последний. При этом, если мы хотим поменять направление сортировки, то достаточно поменять местами аргументы:
langs.sort((v1, v2) -> Integer.compare(v2.length(), v1.length()));
System.out.println(langs); // [javascript, python, ruby, php]
Даже в случае объектов, сортировка почти всегда сводится к сравнению примитивных типов данных. Ниже пример сортировки пользователей по возрасту:
var users = /* список пользователей */;
users.sort((u1, u2) -> Integer.compare(u1.getAge(), u2.getAge()));
Для полноты картины и понимания статей в интернете, рассмотрим альтернативный вариант сортировки, который делает то же самое что и примеры выше, но с применением встроенного класса Comparator
:
langs.sort(Comparator.comparingInt((v) -> v.length()));
users.sort(Comparator.comparingInt((v) -> v.getAge()));
Comparator.comparingInt() принимает на вход лямбда-функцию, которая принимает на вход сравниваемые данные и должна вернуть числовое значение, полученное на базе этих данных для сравнения.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты
Для полного доступа к курсу нужен базовый план
Базовый план откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.