Рубрики
Без рубрики

Введение в Java Stream API

Впервые опубликовано в моем блоге Java Stream API существует с Java 8. Он используется для выражения вычислений… С тегами java, streams, functional.

Впервые опубликовано на моем блог

Java Stream API существует с Java 8. Он используется для выражения вычислений по данным коротким и элегантным способом. В следующем посте я познакомлю вас с наиболее распространенными методами, чтобы дать вам представление о том, чего вы можете достичь с помощью Java Stream API.

Прежде чем перейти непосредственно к коду, я хочу объяснить разницу между потоками и коллекциями. Ясно, что у обоих есть общие свойства, они оба могут быть повторены, например. Вы можете перебирать внешнюю коллекцию с помощью, например, для каждого цикла. Вместо этого вы не выполняете явный цикл через потоки. Вы выражаете свои вычисления функциональным способом, а Stream API обрабатывает итерации внутри. Кроме того, Stream API является ленивым, его элементы вычисляются или извлекаются по сети по запросу. Коллекции – это хранилище данных в памяти, что означает, что каждый элемент вашей коллекции должен быть вычислен и сохранен в вашей оперативной памяти, прежде чем вы сможете получить к нему доступ. Но это не означает, что вы не можете использовать потоки для уже вычисленных данных. Это скорее делает потоки более гибкими, чем коллекции в конкретных ситуациях. Вы также можете создавать потоки из структур данных на основе коллекций, как я сделаю в следующих примерах.

Далее я покажу вам несколько примеров использования потоков, а также сравню свое решение с классическим подходом к программированию.

фильтр

Если вы хотите отфильтровать список, вы можете просто использовать filter .

Давайте предположим, что у нас есть список слов.

List words = 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 вам также никогда больше не придется писать подобный код

List numbers = 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 .

List numbers = 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”