Падручнік Java 8 Streams з прыкладамі кода

У гэтым паведамленні ў блогу мы абмяркуем асаблівасці Java 8 Streams і прадставім мноства розных прыкладаў кода.

Java Streams забяспечваюць функцыянальнае праграмаванне ў Java, і яны падтрымліваюцца, пачынаючы з Java 8, таму, калі ў вас старая версія Java, вам трэба перайсці на java 8, каб выкарыстоўваць Java Streams.



Навошта выкарыстоўваць Java Streams?

Некаторыя перавагі патокаў:


  • Патокі зробяць вас больш эфектыўным праграмістам Java (вы ўбачыце, што з вельмі невялікай колькасцю радкоў кода вы сапраўды можаце дасягнуць даволі шмат, выкарыстоўваючы патокі).
  • Яны актыўна выкарыстоўваюць лямбда-выразы, якія з'яўляюцца своеасаблівымі аднаразовымі функцыямі.
  • ParallelStreams вельмі лёгка дазваляе шматструменныя аперацыі для вялікіх набораў дадзеных.


Паток трубаправода

У большасці выпадкаў трубаправод патокаў складаецца з

  • крыніца (адкуль выцякаюць вашы дадзеныя)
  • затым нуль і больш прамежкавыя аперацыі
  • і адзін праца тэрмінала

Java Streams - фільтр, карта, памяншэнне


Крыніца збіраецца трансліраваць паток элементаў.



Гэты паток элементаў можна адфільтраваць, адсартаваць, адлюстраваць альбо нанесці іншы шэраг аперацый, якія прымяняюцца да кожнага элемента.

У рэшце рэшт, гэта можа быць альбо збор, альбо памяншэнне, альбо нейкая іншая аперацыя тэрмінала, але выконваецца толькі адна аперацыя тэрмінала.

Крыніца патоку

Крыніца патоку можа паходзіць з калекцый, спісаў, набораў, масіваў int, longs, double, радкоў і г.д.


Патоковыя аперацыі

Патоковыя аперацыі альбо прамежкавыя, альбо канчатковыя:

  • Прамежкавыя аперацыі такія як фільтр, карта ці сартаванне вяртаюць паток, каб мы маглі звязаць некалькі прамежкавых аперацый.
  • Тэрмінальныя аперацыі атрымаць паток, і яны могуць альбо вярнуць пустэчу, альбо могуць вярнуць невыток, напрыклад, памяншэнне, напрыклад паменшыць элементы ў спіс.

Прамежкавыя аперацыі

  • Дапускаецца нуль і больш прамежкавых аперацый.
  • Парадак мае значэнне; для вялікіх набораў дадзеных: фільтр спачатку затым адсартаваць альбо адлюстраваць.
  • Для вельмі вялікіх набораў дадзеных мы выкарыстоўваем ParallelStream для ўключэння некалькіх патокаў.

Некаторыя прамежкавыя аперацыі ўключаюць:

  • anyMatch ()
  • выразна ()
  • фільтр ()
  • findFirst ()
  • плоская карта ()
  • карта ()
  • прапусціць ()
  • адсартавана ()

Аперацыі тэрмінала

Дапускаецца толькі адна аперацыя тэрмінала.

  • forEach ужывае адну і тую ж функцыю да кожнага элемента, напрыклад, друкуе кожны элемент.
  • collect захоўвае ўсе элементы ў калекцыі альбо ў спісе альбо ў масіве.
  • усе астатнія параметры памяншаюць паток да аднаго элемента зводкі.

Некалькі прыкладаў функцый скарачэння:


  • падлічыць ()
  • макс ()
  • мін ()
  • паменшыць ()


Прыклады кода Java Streams

Зараз давайце паглядзім вышэйзгаданыя паняцці на прыкладах кода.

Цэласны паток

Першы прыклад - проста цэлы паток. Мы збіраемся стварыць цэлалікавы паток, выкарыстоўваючы IntStream клас і яго функцыя дыяпазону, якая дае нам цэлы шэраг.

forEach гэта наш тэрмінал. Для кожнага элемента мы проста збіраемся раздрукаваць яго.

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream

.range(1, 10)

.forEach(System.out::print);
System.out.println();
} }

Выхад:


123456789

Цэлае паток з прапускам

У другім прыкладзе выкарыстоўваецца цэлы паток, але мы дадалі skip() вось, у гэтым выпадку мы збіраемся прапусціць першыя 5 элементаў нашага патоку.

Гэта будзе друкаваць толькі элементы з 6 па 9. Мы таксама выкарыстоўваем просты лямбда-выраз для раздрукоўкі элемента

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
IntStream

.range(1, 10)

.skip(5)

.forEach(x -> System.out.println(x));
System.out.println();
} }

Выхад:

6 7 8 9

Цэлае паток з сумай

Трэці прыклад, мы зноў выкарыстоўваем IntStream аднак, каб стварыць наш паток аб'ектаў, мы змяшчаем яго ў println() аператар як параметр для радка друку.


Тое, што мы збіраемся надрукаваць, гэта проста сума ад 1 да 5, іншымі словамі, 1 2 3 і 4, яна будзе выводзіць толькі суму гэтых лічбаў:

import java.io.IOException; import java.util.stream.IntStream; public class JavaStreams {
public static void main(String[] args) throws IOException {
System.out.println(
IntStream

.range(1, 5)

.sum());
System.out.println();
} }

Выхад:

10

Stream.of

У наступным прыкладзе выкарыстоўваецца Stream.of функцыя, што вельмі зручна, таму што вы можаце перадаваць цэлыя лікі, значэнні з плаваючай кропкай, радкі і нават аб'екты.

У гэтым прыкладзе мы проста зробім прамы алфавітны сартаванне, пасля чаго знойдзем першы элемент, выкарыстоўваючы findFirst() функцыя. Затым мы проста раздрукоўваем першы пункт у спісе.

import java.io.IOException; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream.of('Ava', 'Aneri', 'Alberto')

.sorted()

.findFirst()

.ifPresent(System.out::println);
} }

Выхад

Alberto

Стрым з масіва, сартаванне, фільтраванне і раздрукоўка

У наступным прыкладзе мы збіраемся трансліраваць з масіва. Тады мы будзем сартаваць, фільтраваць, а потым раздрукоўваць.

Тут мы адфільтруем элементы, якія пачынаюцца з s.

Мы выкарыстоўваем лямбда-выраз, які прымае X гэта кожнае імя, а потым правяраецца, якое пачынаецца з літары s і гэта перадасць.

Тады мы будзем сартаваць іх, а затым для кожнага элемента, які праходзіць гэты сартаванне, мы надрукуем яго.

import java.io.IOException; import java.util.Arrays; public class JavaStreams {
public static void main(String[] args) throws IOException {
String[] names = {'Al', 'Ankit', 'Kushal', 'Brent', 'Sarika', 'amanda', 'Hans', 'Shivika', 'Sarah'};
Arrays.stream(names)


.filter(x -> x.startsWith('S'))


.sorted()


.forEach(System.out::println);
} }

Выхад:

Sarah Sarika Shivika

Сярэдняе значэнне цэлага масіва

Зараз давайце паглядзім, як мы можам прыняць сярэдняе значэнне квадратаў масіва int.

Тут мы выкарыстоўваем Arrays.stream() функцыя для перадачы цэлых лікаў, і тады мы будзем выкарыстоўваць map() для супастаўлення кожнага элемента з цэлым лікам да яго квадрата.

import java.util.Arrays; public class JavaStreams {
public static void main(String[] args) {
Arrays.stream(new int[] {2, 4, 6, 8, 10})


.map(x -> x * x)


.average()


.ifPresent(System.out::println);
} }

Выхад:

44.0

Звярніце ўвагу, што ён выводзіць двайны замест цэлага ліку.

Стрым з спісу, фільтр і раздрукоўка

У гэтым прыкладзе мы збіраемся трансляваць са спісу, фільтраваць гэтыя элементы, а потым раздрукоўваць.

Звярніце ўвагу, што ў межах map() функцыя, мы збіраемся пераўтварыць усе імёны ў малую.

import java.util.Arrays; import java.util.List; public class JavaStreams {
public static void main(String[] args) {
List people = Arrays.asList('Al', 'Ankit', 'Brent', 'Sarika', 'amanda', 'Hans', 'Shivika', 'Sarah');
people


.stream()


.map(String::toLowerCase)


.filter(x -> x.startsWith('a'))


.forEach(System.out::println);
} }

Выхад:

al ankit amanda

Мы бачым, што ў нас ёсць тры назвы, якія пачынаюцца з a і ўсе яны ў маленькай літары.

Трансляцыя радкоў з тэкставага файла, сартаванне, фільтраванне і раздрукоўка

У наступным прыкладзе мы збіраемся трансліраваць радкі з тэкставага файла. Мы збіраемся сартаваць, фільтраваць і раздрукоўваць.

Дапусцім, у нас ёсць файл, які называецца bands.txt са зместам, паказаным ніжэй:

Rolling Stones Lady Gaga Jackson Browne Maroon 5 Arijit Singh Elton John John Mayer CCR Eagles Pink Aerosmith Adele Taylor Swift

Мы будзем выкарыстоўваць Files.lines() каб стварыць наш паток, які збіраецца даць нам паток радка для кожнага радка файла.

Пасля таго, як у нас ёсць паток, мы адсартуем іх і адфільтруем элементы, якія перавышаюць 13 сімвалаў, а затым раздрукуем тыя, што засталіся.

Нарэшце, мы павінны закрыць файл, таму мы робім bands.close.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream bands = Files.lines(Paths.get('bands.txt'));
bands


.sorted()


.filter(x -> x.length() > 13)


.forEach(System.out::println);
bands.close();
} }

Выхад:

Jackson Browne Rolling Stones

Мы атрымліваем дзве групы, якія маюць больш за 13 сімвалаў.

Перадайце радкі з тэкставага файла і захавайце ў Спіс

У гэтым прыкладзе мы будзем выкарыстоўваць той жа тэкставы файл, што і вышэй.

Мы хочам адфільтраваць элементы, якія ўтрымліваюць літары jit, выкарыстоўваючы x.contains() што проста функцыя радка.

Выкарыстанне .collect() дадаем усе з літарамі jit у спіс.

Пасля таго, як у нас ёсць спіс, мы можам выкарыстоўваць forEach аператар для раздрукоўкі элементаў.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.List; import java.util.stream.Collectors; public class JavaStreams {
public static void main(String[] args) throws IOException {
List bands2 = Files.lines(Paths.get('bands.txt'))


.filter(x -> x.contains('jit'))


.collect(Collectors.toList());
bands2.forEach(x -> System.out.println(x));
} }

Выхад:

Arijit Singh

Перадайце радкі з файла CSV і падлічыце

У гэтым прыкладзе мы трансліруем радкі з файла CSV і збіраемся падлічыць добрыя радкі.

Дапусцім, у нас ёсць файл, які называецца data.txt са наступным зместам:

A,12,3.7 B,17,2.8 C,14,1.9 D,23,2.7 E F,18,3.4

Тут радок E не мае дадзеных, таму мы хочам выключыць гэты з нашага патоку.

У наступным кодзе мы будзем чытаць у кожным радку, пасля чаго нам трэба падзяліць коскі на масіў, каб кожны радок стаў масівам элементаў.

Затым мы ўжываем фільтр для фільтрацыі радкоў, у якіх няма трох элементаў.

import java.io.IOException; import java.nio.file.Files; import java.nio.file.Paths; import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) throws IOException {
Stream rows1 = Files.lines(Paths.get('data.txt'));
int rowCount = (int)rows1


.map(x -> x.split(','))


.filter(x -> x.length == 3)


.count();
System.out.println(rowCount + ' rows.');
rows1.close();
} }

Выхад:

5 rows

Зніжэнне - сума

Гэты прыклад паказвае, як выкарыстоўваць памяншэнне. Мы збіраемся скараціць да сумы. Тут мы маем двайны паток з выкарыстаннем Stream.of() функцыя. Мы вызначылі тры дублі ў трох розных аргументах і будзем выкарыстоўваць функцыю скарачэння.

import java.util.stream.Stream; public class JavaStreams {
public static void main(String[] args) {
double total = Stream.of(7.3, 1.5, 4.8)


.reduce(0.0, (Double a, Double b) -> a + b);
System.out.println('Total = ' + total);
} }

Выхад:

13.600000000000001