Впервые опубликовано на моем блог
Java Stream API существует с Java 8. Он используется для выражения вычислений по данным коротким и элегантным способом. В следующем посте я познакомлю вас с наиболее распространенными методами, чтобы дать вам представление о том, чего вы можете достичь с помощью Java Stream API.
Прежде чем перейти непосредственно к коду, я хочу объяснить разницу между потоками и коллекциями. Ясно, что у обоих есть общие свойства, они оба могут быть повторены, например. Вы можете перебирать внешнюю коллекцию с помощью, например, для каждого цикла. Вместо этого вы не выполняете явный цикл через потоки. Вы выражаете свои вычисления функциональным способом, а Stream API обрабатывает итерации внутри. Кроме того, Stream API является ленивым, его элементы вычисляются или извлекаются по сети по запросу. Коллекции – это хранилище данных в памяти, что означает, что каждый элемент вашей коллекции должен быть вычислен и сохранен в вашей оперативной памяти, прежде чем вы сможете получить к нему доступ. Но это не означает, что вы не можете использовать потоки для уже вычисленных данных. Это скорее делает потоки более гибкими, чем коллекции в конкретных ситуациях. Вы также можете создавать потоки из структур данных на основе коллекций, как я сделаю в следующих примерах.
Далее я покажу вам несколько примеров использования потоков, а также сравню свое решение с классическим подходом к программированию.
фильтр
Если вы хотите отфильтровать список, вы можете просто использовать filter
.
Давайте предположим, что у нас есть список слов.
Listwords = Arrays.asList("Abra", "Kadrabra", "Aloha");
Теперь мы хотим отфильтровать все слова, начинающиеся с заглавной буквы А, и распечатать их.
words.stream() .filter(word -> word.startsWith("A")) .forEach(System.out::println);
На самом деле мы здесь используем два потоковых метода. Сначала мы преобразуем список в поток и фильтруем и слова, которые начинаются с заглавной буквы A. В результирующем потоке мы печатаем каждое слово с помощью System.out.println
.
Вы, вероятно, видели подобные лямбда-выражения, такие как on в filter
, раньше, но, возможно, вы не видели многих из них, которые я использовал в методе forEach
. System.out::println
– это просто синтаксический сахар для следующего лямбда-выражения: x -> System.out.println(x)
.
Мы также можем написать код, не используя потоки, просто используя цикл for:
for (String word : words) { if (word.startsWith("A")) { System.out.println(word); } }
Это решение, на мой взгляд, менее элегантно и может быть написано более выразительно, как я показал в верхнем фрагменте кода.
Мы даже можем улучшить ваш пример потока, создав метод для условия StartsWith
во внешнем методе.
words.stream() .filter(StreamExamples::startsWithA) .forEach(System.out::println);
с
private static boolean startsWithA(String word) { return word.startsWith("A"); }
сумма
С помощью Stream API вам также никогда больше не придется писать подобный код
Listnumbers = Arrays.asList(1, 2, 3, 4, 5); int sum = 0; for (Integer number : numbers) { sum += number; } System.out.println(sum);
Вместо этого вы можете написать
System.out.println(numbers.stream().mapToInt(Integer::intValue).sum());
который делает точно то же самое, что и верхний фрагмент кода.
карта
map
проецирует каждый элемент потока в другую форму. Поскольку я использовал mapToInt
для проецирования элемента на него, я могу использовать map для проецирования каждого элемента потока в новый элемент.
numbers.stream() .map(number -> number * number) .forEach(System.out::println);
Традиционным подходом к написанию этого кода был бы следующий фрагмент кода:
for (Integer number : numbers) { int squaredNumber = number * number; System.out.println(squaredNumber); }
Плоская карта
Далее давайте предположим, что у нас есть следующий источник данных:
List> matrix = Arrays.asList(Arrays.asList(1, 2), Arrays.asList(3, 4), Arrays.asList(5, 6));
Теперь наша задача состоит в том, чтобы суммировать все элементы в матрице.
Чтобы выровнять структуру данных, мы можем использовать Плоская карта
. Он объединяет потоки и в результате генерирует единый поток. Итак, чтобы вычислить сумму, мы можем сначала использовать flatMap
для объединения нескольких потоков в один, а затем использовать точка отображения
и sum
, как показано в верхнем примере sum
.
System.out.println(matrix.stream().flatMap(Collection::stream).mapToInt(Integer::intValue).sum());
flatMap
позволяет использовать воздерживаться от for-циклов в for-циклах и писать элегантный код в одной строке.
Ваши коллеги будут благодарны вам, если они извлекут ваш код.
собирать
И последнее, но не менее важное: вы можете преобразовать поток в традиционную структуру данных, используя collect
.
Listnumbers = Arrays.asList(1, 2, 3, 4, 5, 6); List evenNumbers = numbers.stream().filter(x -> x % 2 == 0).collect(Collectors.toList());
Я загрузил все примеры на свой Github
Java 8 представила Java Streams, которая позволяет нам выражать запросы обработки данных коротким функциональным и элегантным способом. Есть еще много операций для изучения, этот пост должен просто познакомить вас с Stream API. Я надеюсь, что теперь у вас есть мотивация использовать Stream API в следующий раз, когда вы используете Java.
Оригинал: “https://dev.to/lschultebraucks/introduction-to-java-stream-api-31ie”