Статьи

Извлечение элементов коллекции Java — Java 8 Way

Мы все широко использовали классы Collection, такие как List, Map и их производные версии. И каждый раз, когда мы использовали их, нам приходилось перебирать их, чтобы либо найти какой-то элемент, либо обновить элементы, либо найти разные элементы, соответствующие некоторому условию. Рассмотрим список лиц, как показано ниже:

List<Person> personList = new ArrayList<>();
personList.add(new Person("Virat", "Kohli",22));
personList.add(new Person("Arun", "Kumar",25));
personList.add(new Person("Rajesh", "Mohan", 32));
personList.add(new Person("Rahul", "Dravid", 35));

Чтобы узнать все экземпляры Person с возрастом более 30, мы бы сделали:

List<Person> olderThan30OldWay = new ArrayList<>();
for ( Person p : personList){
  if ( p.age >= 30){
    olderThan30OldWay.add(p);
  }
}
System.out.println(olderThan30OldWay);

и это дает мне вывод как:

[Rajesh Mohan, 32, Rahul Dravid, 35]

Код легко написать, но не более ли он многословен, особенно часть итерации? Почему мы должны повторяться? Разве не было бы здорово, если бы существовал API, который итерировал бы содержимое и давал бы нам конечный результат, то есть мы даем исходный список и используем серию вызовов методов, чтобы получить нам искомый список результатов? Да, это возможно в других языках, таких как Scala, Groovy, которые поддерживают проходящие замыкания, а также поддерживают внутреннюю итерацию. Но есть ли решение для разработчиков Java? Да, эта точная проблема решается путем введения поддержки лямбда-выражений (замыканий) и расширенного API-интерфейса Collection для использования поддержки лямбда-выражений. Печальная новость заключается в том, что она станет частью Java 8 и займет некоторое время. быть в основном развитии.

Использование улучшений Java 8 в вышеупомянутом сценарии

Как я уже говорил, API-интерфейс Collections расширяется для поддержки использования лямбда-выражений, и подробнее об этом можно прочитать здесь . Вместо добавления всех новых API в класс Collection команда JDK создала новую концепцию под названием «Поток» и добавила большинство API в этом классе. «Поток» — это последовательность элементов, полученных из Коллекции, из которой она создана. Чтобы узнать больше о происхождении класса Stream, пожалуйста, обратитесь к этому документу .

Для реализации примера, который я начал с использования улучшений в Java 8, мы будем использовать несколько новых API, а именно: stream (), filter (), collect (), Collectors.toCollection ().
stream () : использует коллекцию, в которой вызывается этот API, для создания экземпляра класса Stream .
filter () : этот метод принимает лямбда-выражение, которое принимает один параметр и возвращает логическое значение. Это лямбда-выражение написано как замена для реализации класса Predicate .
collect () : есть 2 перегруженные версии этого метода. Тот, который я использую здесь, берет экземпляр Collector, Этот метод берет содержимое потока и создает другую коллекцию. Эта логика построения определяется Коллектором .
Collectors.toCollection () : Collectors — это фабрика для Collector . И toCollection () принимает ссылку на лямбда-выражение / метод, которая должна возвращать новый экземпляр любых производных класса Collection.

Кратко ознакомившись с используемыми API, позвольте мне показать код, эквивалентный первому примеру кода:

List<Person> olderThan30 = 
    //Create a Stream from the personList
    personList.stream().
    //filter the element to select only those with age >= 30
    filter(p -> p.age >= 30).
    //put those filtered elements into a new List.
    collect(Collectors.toCollection(() -> new ArrayList<Person>()));
System.out.println(olderThan30);

Приведенный выше код использует как внутреннюю итерацию, так и лямбда-выражения, чтобы сделать его интуитивно понятным, лаконичным и приятным для глаз.
Если вы не знакомы с идеей лямбда-выражений, ознакомьтесь с моей предыдущей записью, в которой кратко описываются лямбда-выражения.