Константин
Деңгээл

Stream API

Группада жарыяланган
Stream API - 1

Stream API деген эмне?

Stream API - бул функционалдык стилдеги маалымат структуралары менен иштөөнүн жаңы жолу. Stream API (бир компьютердик программанын башка программа менен байланыша ала турган жолдорунун сүрөттөлүшү) анын өзөгүн маалымат агымы түзөт. "Жип" деген терминдин өзү жалпысынан программалоодо жана өзгөчө Java тorнде бир топ бүдөмүк.
Stream API - 1
Java 8дин пайда болушу менен, Stream API программисттерге мурун көп саптарды талап кылган нерселерди кыскараак жазууга мүмкүндүк берди, тактап айтканда, маалымат топтомдору менен иштөөнү жөнөкөйлөштүрүү, атап айтканда, чыпкалоо, сорттоо жана башка маалыматтарды манипуляциялоо операцияларын жөнөкөйлөтүү. Эгерде сизде аралык операциялар жок болсо, анда сиз көп учурда агымсыз жасай аласыз жана жасашыңыз керек, антпесе code агымсыз караганда татаалыраак болот.
Stream API - 2
Эмнеден баштоо керек? Бизге керек болгон чогултууга, массивге же методго негизделген Stream инстанциясын түзүүдөн жана ошого жараша маалыматтар кайдан алынат:
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 API - 3
  • Бош агым:Stream.empty()
  • Тизмеден агым:list.stream()
  • Картадан агым:map.entrySet().stream()
  • Массивден агым:Arrays.stream(array)
  • Көрсөтүлгөн элементтерден агым:Stream.of("1", "2", "3")
Андан ары операторлор (негизинен Stream классынын методдору) деген нерсе бар.Операторлорду эки топко бөлүүгө болот:
  • Аралык ("жалкоо" деп да аталат) - кириш элементтерди иштеп чыгуу жана агымды кайтаруу. Элементтерди иштетүү чынжырында көптөгөн аралык операторлор болушу мүмкүн.
  • Терминал («терминал», ошондой эле «эркин» деп аталат) - элементтерди иштеп чыгуу жана агымды токтотуу, ошондуктан чынжырда бир гана терминал оператору болушу мүмкүн.
Мисал:
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)), ал өз кезегинде ага өткөн коллекциянын бардык элементтери аркылуу өтүп, аны көрсөтөт)
Stream API - 5
Маанилүү пункттар:
  • Терминал оператору чакырылмайынча иштетүү башталbyte. list.stream().filter(s -> s > 5)(тизмеден бир дагы элементти алbyte);
  • Агымдын мисалы бир жолудан ашык колдонулbyte =( ;
  • 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 пакетине кошулган орнотулган функционалдык интерфейс. “ 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(Функциянын картасы)
Жана салыштыруу үчүн дагы бир мисал, flatMap:
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
Терминал операторлору:
Stream API - 8
  • 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 түрүнө айландыруучу жана сумманы эсептеген коллектор.

Пайдалуу шилтемелер: PS: Бизди лайк басуудан тартынбаңыз ^ : ^
Комментарийлер
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION