Stream API деген эмне?
Stream API - бул функционалдык стилдеги маалымат структуралары менен иштөөнүн жаңы жолу. Stream API (бир компьютердик программанын башка программа менен байланыша ала турган жолдорунун сүрөттөлүшү) анын өзөгүн маалымат агымы түзөт. "Жип" деген терминдин өзү жалпысынан программалоодо жана өзгөчө Java тorнде бир топ бүдөмүк.List<String> list = new ArrayList<String>();
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();
Жогоруда айтылгандай, Stream API codeдун саптарынын санын кыскартууга мүмкүндүк берет. Агым менен мисал:
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 = {50, 60, 70, 80, 90, 100, 110, 120
int count = 0;
for (int x : arr) {
if (x >= 90) continue;
x += 10;
count++;
if (count > 3) break;
System.out.print(x);
}
Агымды түзүүнүн мүмкүн болгон жолдору:
- Бош агым:
Stream.empty()
- Тизмеден агым:
list.stream()
- Картадан агым:
map.entrySet().stream()
- Массивден агым:
Arrays.stream(array)
- Көрсөтүлгөн элементтерден агым:
Stream.of("1", "2", "3")
- Аралык ("жалкоо" деп да аталат) - кириш элементтерди иштеп чыгуу жана агымды кайтаруу. Элементтерди иштетүү чынжырында көптөгөн аралык операторлор болушу мүмкүн.
- Терминал («терминал», ошондой эле «эркин» деп аталат) - элементтерди иштеп чыгуу жана агымды токтотуу, ошондуктан чынжырда бир гана терминал оператору болушу мүмкүн.
1.List<String> list = new ArrayList<String>();
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 - an object түзүү
Stream
; - 13 - метод
filter
(фильтр) - аралык оператор,x
санап чыгуу үчүн коллекциянын бир элементине барабар (менен сыяктууfor each
) жана -> кийин -> биз коллекциябыз кантип чыпкаланганын көрсөтөбүз жана бул аралык оператор болгондуктан, чыпкаланган коллекция андан ары ыкмага өтөт ,forEach
бул өз кезегинде санап чыгуунун терминалдык (акыркы) аналогуfor each
(System.out::println
: үчүн кыска сөзx-> System.out.println(x))
, ал өз кезегинде ага өткөн коллекциянын бардык элементтери аркылуу өтүп, аны көрсөтөт)
- Терминал оператору чакырылмайынча иштетүү башталbyte.
list.stream().filter(s -> s > 5)
(тизмеден бир дагы элементти алbyte); - Агымдын мисалы бир жолудан ашык колдонулbyte =( ;
Ошондуктан, ар бир жолу жаңы:
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));
filter(Predicate predicate)
агымды чыпкалайт, шарттан өткөн элементтерди гана өткөрөт (Predicate – Java SE 8 пакетине кошулган орнотулган функционалдык интерфейс. “ true ” жана “ falsejava.util.function
” маанисин текшерет );map(Function mapper)
ар бир элементти өзгөртүп, андан ары өткөрүп жибере турган функцияны түзүүгө мүмкүндүк берет (Функционалдык интерфейсFunction<T,R>
T түрүндөгү an objectтен R түрүндөгү an objectке өтүү функциясын билдирет)flatMap(Function<T, Stream<R>> mapper)
- сыяктуу элеmap
, алар примитивдүү агымга айландыруу үчүн колдонулат.
[stream1,stream2,stream3,stream4] => stream
.
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.flatMap(Arrays::stream).distinct() //aligns each generated thread into a single thread
.collect(Collectors.toList()).forEach(System.out::println);
map
Ал жиптердин тизмесине (тактап айтканда, <Stream>
жиптерге) айланганда [stream1,stream2,stream3,stream4] =>Stream.of(stream1,stream2,stream3,stream4)
:
String[] array = {"Java", "Ruuuuussshhh"};
Stream<String> streamOfArray = Arrays.stream(array);
streamOfArray.map(s->s.split("")) //Convert the word to an array of letters
.map(Arrays::stream).distinct() //Make the array into a separate thread
.collect(Collectors.toList()).forEach(System.out::println);
менен салыштырганда дагы бир айырмачылык map
, сиз бир элементти нөлгө, бир же башка көптөгөн элементтерге алмаштыра аласыз. Бир элементти нөл элементтерге айландыруу үчүн , null
же бош агымды кайтарышыңыз керек. Бир элементке айландыруу үчүн, бир элементтен агымды кайтарышыңыз керек, мисалы, аркылуу Stream.of(x)
. Бир нече элементтерди кайтаруу үчүн, сиз каалаган ыкма менен бул элементтер менен агым түзө аласыз. Ошол эле flatMap ыкмасы, бирок Double, Integer жана Long үчүн:
- flatMapToDouble(Функцияны түзүүчү)
- flatMapToInt(Функциянын картасы)
- flatMapToLong(Функциянын картасы)
Stream.of(2, 3, 0, 1, 3)
.flatMapToInt(x -> IntStream.range(0, x))
.forEach(System.out::print);// 010120012
-
IntStream.range(0,x) – элементтерди 0 (кошкондо) дан x (кошпогон) агымга чыгарат;
карта:
Stream.of(2, 3, 0, 1, 3) .map(x -> IntStream.range(0, x)) .forEach(System.out::print);//list of streams (streams);
-
limit(long maxSize) – агымды элементтердин саны менен чектейт:
stream.limit(5).forEach(x -> System.out.println(x));
-
skip(long n) – n элементтерди өткөрүп жиберүү:
stream.skip(3).forEach(x -> System.out.println(x));
-
сорттолгон()
- сорттуу(Салыштыруучу компаратор) – агымды иреттейт (TreeMap сыяктуу сорттоо):
stream.sorted().forEach(x -> System.out.println(x));
-
distinct() — элементтердин уникалдуулугун текшерет (элементтердин кайталануусун жок кылат);
-
dropWhile(Predicate predicate) - шартты канааттандырган элементтерди өткөрүп жиберет (java 9да пайда болгон, Predicate<T> функционалдуу интерфейси кандайдыр бир шарттын аткарылганын текшерет. Эгер ал аткарылса, анда чындык кайтарылат. Lambda туюнтмасы типтеги an objectти алат. параметр катары T:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach(Керектөөчү аракети) – ар бири үчүн аналогу (Керектөөчү<T> эч нерсе кайтарбастан T түрүндөгү an objectте кандайдыр бир иш-аракеттерди аткарат);
-
count() – агым элементтеринин санын кайтарат:
System.out.println(stream.count());
-
чогултуу(Коллектор жыйноочу) – ыкма бардык элементтерди тизмеге, топтомго же башка коллекцияга чогултат, элементтерди кандайдыр бир критерийге ылайык топтойт, баарын сапка бириктирет ж.б.:
List<String> list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList());
-
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
— сыяктуу эле,collect(collector)
ыңгайлуулук үчүн параметрлери гана бөлүнгөн (supplier
жаңы an objectтерди (контейнерлерди) берет, мисалыnew ArrayList()
,accumulator
контейнерге элементти кошот,combiner
агымдын бөлүктөрүн бириктирет); -
кыскартуу(T identity, BinaryOperator accumulator) - агымдын бардык элементтерин бир an objectке айлантат (бардык элементтердин суммасын эсептөө, же минималдуу элементти табуу), адегенде an object
identity
жана агымдын биринчи элементи алынат, функция колдонулатaccumulator
жанаidentity
анын натыйжасы болуп калат. Андан кийин калган элементтер үчүн баары уланат.int sum = Stream.of(1, 2, 3, 4, 5).reduce(10, (acc, x) -> acc + x);// = 25
-
reduce(BinaryOperator accumulator)
— жогорудагыдай эле ыкма, бирок баштапкысы жокidentity
, ал агымдын биринчи элементиOptional min(Comparator comparator)
Кошумча max(Салыштыруучу компаратор) өткөн компаратордун негизинде минималдуу/максималдуу элементти издейт; -
findFirst()
– агымдын биринчи элементин чыгарат:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
— агымдын бардык элементтери шартты канааттандырса, чындыкты кайтарат. Эгерде предикат функциясын чакыруунун натыйжасы false болгон кандайдыр бир элемент кездешсе , анда оператор элементтерди сканерлөөсүн токтотуп, false кайтарып берет :Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
-
anyMatch(Predicate predicate)
— эгерде агымдын жок дегенде бир элементи шартты канааттандырса, чындыкты кайтаратpredicate
:Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
-
noneMatch(Predicate predicate)
— эгер агымдын бардык элементтеринен өтүп, алардын бири да шартты канааттандырбаса, чындыкка кайтарылатpredicate
:Stream.of(1, 2, 3, 4, 9).noneMatch(x -> x >= 7);//false
Collectors
:
-
toList()
- элементтерди чогултатList
:List<Integer> list = Stream.of(99, 2, 3).collect(Collectors.toList());
-
toSet()
- элементтерди топтомго чогултат:Set<Integer> set = Stream.of(99, 2, 3).collect(Collectors.toSet());
-
counting()
— Элементтердин санын эсептейт:Long count = Stream.of("1", "2", "3", "4").collect(Collectors.counting());
-
joining()
-
joining(CharSequence delimiter)
-
joining(CharSequence delimiter, CharSequence prefix, CharSequence suffix)
— элементтерди бир сапка чогултат. Кошумча, сиз бөлүүчүнү, ошондой эле бүт ырааттуулук үчүн префикс менен суффиксти көрсөтө аласыз: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 ]
-
summingInt(ToIntFunction mapper)
-
summingLong(ToLongFunction mapper)
-
summingDouble(ToDoubleFunction mapper)
- an objectтерди int/long/double түрүнө айландыруучу жана сумманы эсептеген коллектор.
GO TO FULL VERSION