Java stream api туториал

Stream API

Java-университет

Stream API — это новый способ работать со структурами данных в функциональном стиле. Stream (поток) API (описание способов, которыми одна компьютерная программа может взаимодействовать с другой программой) — это по своей сути поток данных. Сам термин «поток» довольно размыт в программировании в целом и в Java в частности.

Stream API - 1

С появлением Java 8 Stream API позволило программистам писать существенно короче то, что раньше занимало много строк кода, а именно — упростить работу с наборами данных, в частности, упростить операции фильтрации, сортировки и другие манипуляции с данными. Если у вас промежуточных операций нет, часто можно и нужно обойтись без стрима, иначе код будет сложнее чем без потока.

Stream API - 2

C чего, собственно, начать? С создания экземпляра Stream, который опирается на нужную нам коллекцию, массив или метод их и откуда соответственно будут браться данные:

 List list = new ArrayList(); list.add("One"); list.add("Two"); list.add("Three"); list.add("Four"); list.add("Five"); list.add("Six"); list.add("Seven"); list.add("Eight"); list.add("Nine"); list.add("Ten"); Stream stream = list.stream(); 
 IntStream.of(50, 60, 70, 80, 90, 100, 110, 120).filter(x -> x < 90).map(x ->x + 10) .limit(3).forEach(System.out::print); 
 int[] arr = = 90) continue; x += 10; count++; if (count > 3) break; System.out.print(x); > 

Stream API - 3

  • Пустой стрим: Stream.empty()
  • Стрим из List: list.stream()
  • Стрим из Map: map.entrySet().stream()
  • Стрим из массива: Arrays.stream(array)
  • Стрим из указанных элементов: Stream.of(«1», «2», «3»)
  • Промежуточные (“intermediate”, ещё называют “lazy”) — обрабатывают поступающие элементы и возвращают стрим. Промежуточных операторов в цепочке обработки элементов может быть много.
  • Терминальные (“terminal”, ещё называют “eager”) — обрабатывают элементы и завершают работу стрима, так что терминальный оператор в цепочке может быть только один.
 1.List list = new ArrayList(); 2.list.add("One"); … 11.list.add("Ten"); 12.Stream stream = list.stream(); 13.stream.filter(x-> x.toString().length() == 3).forEach(System.out::println); 
  • 1 — создаём список list ;
  • 2-11 — заполняем его тестовыми данными;
  • 12 — создаём обьект Stream ;
  • 13 — метод filter (фильтр) — промежуточный оператор, x приравнивается к одному элементу коллекции для перебора (как при for each ) и после -> мы указываем как фильтруется наша коллекция и так как это промежуточный оператор, отфильтрованная коллекция идёт дальше в метод forEach который в свою очередь является терминальным (конечным) аналогом перебора for each (Выражение System.out::println сокращенно от: x-> System.out.println(x)) , которое в свою очередь проходит по всем элементам переданной ему коллекции и выводит её)

Stream API - 5

  • Обработка не начнётся до тех пор, пока не будет вызван терминальный оператор. list.stream().filter(s -> s > 5) (не возьмёт ни единого элемента из списка);
  • Экземпляр, стрима нельзя использовать более одного раза =( ;
Читайте также:  Python tkinter ввод числа

Stream API - 6

 list.stream().filter(x-> x.toString().length() == 3).forEach(System.out::println); list.stream().forEach(x -> System.out.println(x)); 
 stream.filter(x-> x.toString().length() == 3).map(x -> x + " - the length of the letters is three").forEach(x -> System.out.println(x)); 

Stream API - 7

  • filter(Predicate predicate) фильтрует стрим, пропуская только те элементы, что проходят по условию (Predicate встроенный функциональный интерфейс, добавленный в Java SE 8 в пакет java.util.function . Проверяет значение на “true” и “false”);
  • map(Function mapper) даёт возможность создать функию с помощью которой мы будем изменять каждый элемент и пропускать его дальше (Функциональный интерфейс Function представляет функцию перехода от объекта типа T к объекту типа R)
  • flatMap(Function> mapper) — как и в случае с map , служат для преобразования в примитивный стрим.
 String[] array = ; Stream streamOfArray = Arrays.stream(array); streamOfArray.map(s->s.split("")) //Преобразование слова в массив букв .flatMap(Arrays::stream).distinct() //выравнивает каждый сгенерированный поток в один поток .collect(Collectors.toList()).forEach(System.out::println); 

В то время когда map преобразует в список потоков (точнее потоков) [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4) :

 String[] array = ; Stream streamOfArray = Arrays.stream(array); streamOfArray.map(s->s.split("")) //Преобразование слова в массив букв .map(Arrays::stream).distinct() //Сделать массив в отдельный поток .collect(Collectors.toList()).forEach(System.out::println); 
  • flatMapToDouble(Function mapper)
  • flatMapToInt(Function mapper)
  • flatMapToLong(Function mapper)
 Stream.of(2, 3, 0, 1, 3) .flatMapToInt(x -> IntStream.range(0, x)) .forEach(System.out::print);// 010120012 
 Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//перечень стримов(потоков); 
 stream.limit(5).forEach(x -> System.out.println(x)); 
 stream.skip(3).forEach(x -> System.out.println(x)); 
 stream.sorted().forEach(x -> System.out.println(x)); 
 Predicate isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false 

Stream API - 8

  • forEach(Consumer action) – аналог for each (Consumer выполняет некоторое действие над объектом типа T, при этом ничего не возвращая);
  • count() – возвращает количество елементов стрима: System.out.println(stream.count());
  • collect(Collector collector) – метод собирает все элементы в список, множество или другую коллекцию, сгруппировывает элементы по какому-нибудь критерию, объединяет всё в строку и т.д.:
 List list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList()); 
 int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25 
 Stream.of(1, 2, 3, 4, 9).findFirst(); 
 Stream.of(1, 2, 3, 4, 9).allMatch(x -> x  
 Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true 
 Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false 
 List list = Stream.of(99, 2, 3).collect(Collectors.toList()); 
 Set set = Stream.of(99, 2, 3).collect(Collectors.toSet()); 
 Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting()); 
 String a = Stream.of("s", "u" ,"p", "e", "r").collect(Collectors.joining()); System.out.println(a); // super String b = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining("-")); System.out.println(b); // s-u-p-e-r String c = Stream.of("s", "u", "p", "e", "r").collect(Collectors.joining(" -> ", "[ ", " ]")); System.out.println(c); // [ s -> u -> p -> e -> r ] 

Источник

Java Stream API на простых примерах

Стримы и коллекции чем-то похожи друг на друга, но у них разное назначение. Коллекции обеспечивают эффективный доступ к одиночным объектам, а стримы, наоборот, для прямого доступа и обработки отдельных элементов не используются. Стримы предназначены для параллельных и последовательных агрегаций, выполняемых через цепочку методов.

Давайте сразу перейдем к примерам.

Для начала создадим класс User — основной класс для наших экспериментов.

import lombok.AllArgsConstructor; import lombok.Data; import lombok.ToString; @Data @AllArgsConstructor @ToString public class User

Далее напишем класс Sample , в котором будем запускать наш код.

import java.util.Arrays; import java.util.List; public class Sample < private final ListuserList = Arrays.asList( new User(1, "Michael", "Robert", 37, "TR"), new User(2, "Mary", "Patricia", 11, "EN"), new User(3, "John", "Michael", 7, "FR"), new User(4, "Jennifer", "Linda", 77, "TR"), new User(5, "William", "Elizabeth", 23, "US"), new User(6, "Sue", "Jackson", 11, "IT"), new User(7, "Michael", "Tommy", 37, "EN") ); public static void main(String. args) < Sample sample = new Sample(); >>

1. Перебор всех элементов userList с помощью forEach() и вывод их в консоль.

public static void main(String. args) < Sample sample = new Sample(); sample.test1(); >private void test1()
Test 1 User(id=1, firstName=Michael, lastName=Robert, age=37, nationality=TR) User(id=2, firstName=Mary, lastName=Patricia, age=11, nationality=EN) User(id=3, firstName=John, lastName=Michael, age=7, nationality=FR) User(id=4, firstName=Jennifer, lastName=Linda, age=77, nationality=TR) User(id=5, firstName=William, lastName=Elizabeth, age=23, nationality=US) User(id=6, firstName=Sue, lastName=Jackson, age=11, nationality=IT) User(id=7, firstName=Michael, lastName=Tommy, age=37, nationality=EN)

Так как userList — это ArrayList , то элементы выводятся в консоль в порядке добавления их в список.

2. Перебор всех элементов с выполнением некоторой операции над каждым элементом списка и вывод их на консоль.

private void test2() < System.out.println("Test 2"); userList.stream() .map(u ->< return new User( u.getId(), "X " + u.getFirstName(), "Y " + u.getLastName(), u.getAge() + 10), u.getNationality()); >) .collect(Collectors.toList()) .forEach(System.out::println); >
Test 2 User(id=1, firstName=X Michael, lastName=Y Robert, age=47, nationality=TR) User(id=2, firstName=X Mary, lastName=Y Patricia, age=21, nationality=EN) User(id=3, firstName=X John, lastName=Y Michael, age=17, nationality=FR) User(id=4, firstName=X Jennifer, lastName=Y Linda, age=87, nationality=TR) User(id=5, firstName=X William, lastName=Y Elizabeth, age=33, nationality=US) User(id=6, firstName=X Sue, lastName=Y Jackson, age=21, nationality=IT) User(id=7, firstName=X Michael, lastName=Y Tommy, age=47, nationality=EN)

3. Сортировка списка по свойству age .

Test 3 User(id=3, firstName=John, lastName=Michael, age=7, nationality=FR) User(id=2, firstName=Mary, lastName=Patricia, age=11, nationality=EN) User(id=6, firstName=Sue, lastName=Jackson, age=11, nationality=IT) User(id=5, firstName=William, lastName=Elizabeth, age=23, nationality=US) User(id=1, firstName=Michael, lastName=Robert, age=37, nationality=TR) User(id=7, firstName=Michael, lastName=Tommy, age=37, nationality=EN) User(id=4, firstName=Jennifer, lastName=Linda, age=77, nationality=TR)

4. Сортировка списка по нескольким свойствам: age , firstName , lastName .

Test 4 User(id=3, firstName=John, lastName=Michael, age=7, nationality=FR) User(id=2, firstName=Mary, lastName=Patricia, age=11, nationality=EN) User(id=6, firstName=Sue, lastName=Jackson, age=11, nationality=IT) User(id=5, firstName=William, lastName=Elizabeth, age=23, nationality=US) User(id=1, firstName=Michael, lastName=Robert, age=37, nationality=TR) User(id=7, firstName=Michael, lastName=Tommy, age=37, nationality=EN) User(id=4, firstName=Jennifer, lastName=Linda, age=77, nationality=TR)

5. Вычисление среднего возраста ( age ) и максимальной длины firstName .

private void test5() < System.out.println("Test 5"); double averageAge = userList.stream() .mapToInt(User::getAge) .summaryStatistics() .getAverage(); System.out.print("averageAge: " + averageAge); int maxFirstNameLenght = userList.stream() .mapToInt((value) ->< return value.getFirstName().length(); >) .summaryStatistics() .getMax(); System.out.println(" maxFirstNameLenght: " + maxFirstNameLenght); >
Test 5 averageAge: 29.0 maxFirstNameLenght: 8

6. Проверка, что у всех User возраст ( age ) больше 6.

private void test6() < System.out.println("Test 6"); boolean isAllAgesGreaterThan6 = userList.stream() .allMatch(user ->user.getAge() > 6); System.out.println("isAllAgesGreaterThan6: " + isAllAgesGreaterThan6); >
Test 6 isAllAgesGreaterThan6: true

7. Проверка, есть ли кто-то с firstName , начинающийся с символа S .

private void test7() < System.out.println("Test 7"); boolean isFirstCharS = userList.stream() .anyMatch(user ->user.getFirstName().charAt(0) == 'S'); System.out.println("isFirstCharS " + isFirstCharS); >

8. Преобразование одной коллекцию в другую.

private void test8() < System.out.println("Test 8"); Listlist = userList.stream() .collect(Collectors.toList()); Set set = userList.stream() .collect(Collectors.toSet()); List linkedList = userList.stream() .collect(Collectors.toCollection(LinkedList::new)); Map map = userList.stream() .collect(Collectors.toMap(user -> user.getId(), user -> user)); >

9. Количество разных национальностей (nationality).

Test 9 countDifferentNationalites: 5

10. User старше 10 лет, у которых первый символ firstName не равен M .

private void test10() < System.out.println("Test 10"); userList.stream() .filter(p ->(p.getFirstName().charAt(0) != 'M')) .filter(p -> (p.getAge() > 10)) .collect(Collectors.toList()) .forEach(System.out::println); >
Test 10 User(id=4, firstName=Jennifer, lastName=Linda, age=77, nationality=TR) User(id=5, firstName=William, lastName=Elizabeth, age=23, nationality=US) User(id=6, firstName=Sue, lastName=Jackson, age=11, nationality=IT)

Резюмируя, Java Stream — это не структура хранения данных. Стримы передают элементы из источника (какой-либо структуры данных) через конвейер операций и возвращают некоторое значение, не модифицируя источник.

Все примеры находятся в репозитории GitHub.

Приглашаем всех желающих на открытый урок «Переопределение, скрытие, передекларация». Будет рассмотрено переопределение и скрытие методов в Java, а также передекларация и скрытие переменных. Познакомимся с четырьмя правилами, а потом ещё и с пятым. Регистрация здесь.

Источник

Оцените статью