Константин
Деңгей

Stream API

Топта жарияланған
Stream API - 1

Stream API дегеніміз не?

Stream API функционалдық стильде деректер құрылымдарымен жұмыс істеудің жаңа тәсілі болып табылады. Stream API (бір компьютерлік бағдарламаның басқа бағдарламамен байланысу тәсілдерінің сипаттамасы) оның негізінде деректер ағыны болып табылады. Жалпы бағдарламалауда, атап айтқанда Java тілінде «жіп» терминінің өзі анық емес.
Stream API - 1
Java 8-нің пайда болуымен Stream API бағдарламашыларға бұрын codeтың көп жолын алған нәрсені әлдеқайда қысқаша жазуға мүмкіндік берді, атап айтқанда, деректер жиынымен жұмыс істеуді жеңілдетуге, атап айтқанда, сүзу, сұрыптау және басқа деректерді өңдеу операцияларын жеңілдету. Егер сізде аралық операциялар болмаса, ағынсыз жиі жасай аласыз және істеу керек, әйтпесе 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
Маңызды нүктелер:
  • Терминал операторы шақырылмайынша өңдеу басталмайды. list.stream().filter(s -> s > 5)(тізімнен бірде-бір элемент алынбайды);
  • Ағынның данасын бір реттен артық пайдалануға болмайды =( ;
  • 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 предикаты) – шартты қанағаттандыратын элементтерді өткізіп жібереді (java 9-да пайда болды, Predicate<T> функционалдық интерфейсі қандай да бір шарттың орындалғанын тексереді. Егер ол орындалса, онда шын мәні қайтарылады. Lambda өрнегі типтегі нысанды қабылдайды. 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 идентификаторы, BinaryOperator аккумуляторы) – ағынның барлық элементтерін бір 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(Comparator comparator) берілген компаратор негізінде минималды/максималды элементті іздейді;

  • findFirst()– ағынның бірінші элементін шығарады:

    Stream.of(1, 2, 3, 4, 9).findFirst();
  • allMatch(Predicate predicate)— егер ағынның барлық элементтері шартты қанағаттандырса, true мәнін қайтарады. Егер предикат функциясын шақыру нәтижесі жалған болатын кез келген элемент кездессе , онда оператор элементтерді сканерлеуді тоқтатады және жалған мәнін қайтарады :

    Stream.of(1, 2, 3, 4, 9).allMatch(x -> x <= 7);//false
  • anyMatch(Predicate predicate)— егер ағынның кем дегенде бір элементі шартты қанағаттандырса, true мәнін қайтарады predicate:

    Stream.of(1, 2, 3, 4, 9).anyMatch(x -> x >= 7);//true
  • noneMatch(Predicate predicate)— егер ағынның барлық элементтерінен өтіп, олардың ешқайсысы шартты қанағаттандырмаса, true мәнін қайтарады 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