Java 8деги Java Threads менен таанышуу
Java 8дин бир бөлүгү катары киргизилген Java Streams маалымат жыйнагы менен иштөө үчүн колдонулат. Алар өзүлөрү маалымат структурасы эмес, бирок акыркы натыйжаны алуу үчүн буйрутма жана конвейер аркылуу башка маалымат структураларынан маалыматты киргизүү үчүн колдонулушу мүмкүн. Эскертүү: Агым менен Threadди чаташтырбоо маанилүү, анткени орус тorнде эки термин тең бир эле котормодо “агым” деп аталат. Stream операцияларды аткаруу үчүн an objectти билдирет (көбүнчө берorштерди өткөрүү же сактоо), ал эми Thread (сөзмө-сөз которуу - жип) белгилүү бир программалык codeду башка code бутактары менен параллелдүү аткарууга мүмкүндүк берүүчү an objectти билдирет. Stream өзүнчө маалымат түзүмү болбогондуктан, ал эч качан маалымат булагын өзгөртпөйт. Java агымдары төмөнкү өзгөчөлүктөргө ээ:-
Java Stream "java.util.stream" пакетин колдонуу менен колдонсо болот. Аны codeду колдонуп скриптке импорттоого болот:
import java.util.stream.* ;
Бул codeду колдонуу менен биз Java Streamде бир нече орнотулган функцияларды оңой эле ишке ашыра алабыз.
-
Java Stream Javaдагы коллекциялар жана массивдер сыяктуу маалымат жыйнактарынан киргизүүнү кабыл алат.
-
Java Stream киргизүү маалымат түзүмүн өзгөртүүнү талап кылbyte.
-
Java Stream булагын өзгөртпөйт. Анын ордуна, ал ылайыктуу түтүк ыкмаларын колдонуу менен өндүрүштү түзөт.
-
Java агымдары аралык жана терминалдык операцияларга дуушар болушат, аларды биз кийинки бөлүмдөрдө талкуулайбыз.
-
Java Stream'де аралык операциялар өткөрүлөт жана жалкоо баалоо форматында ишке ашат. Алар терминалдык функциялар менен аяктайт. Бул Java Streamди колдонуу үчүн негизги форматты түзөт.
Java 8де Java агымын түзүү
Java темалары бир нече жол менен түзүлүшү мүмкүн:1. Stream.empty() ыкмасын колдонуу менен бош агым түзүү
Кодуңузда кийинчерээк колдонуу үчүн бош агым түзө аласыз. Эгер сиз Stream.empty() ыкмасын колдонсоңуз , анда эч кандай маанилери жок бош агым түзүлөт. Бул бош агым, эгерде биз иштөө убагында нөл көрсөткүчүн өткөрүп жибергибиз келсе, пайдалуу болушу мүмкүн. Бул үчүн сиз төмөнкү буйрукту колдоно аласыз:Stream<String> str = Stream.empty();
Жогорудагы билдирүү ичинде эч кандай элементи жок str аттуу бош агымды жаратат . Муну текшерүү үчүн str.count() терминин колдонуп агымдын санын же өлчөмүн текшериңиз . Мисалы,
System.out.println(str.count());
Натыйжада, биз чыгарууда 0 алабыз .
2. Stream.Builder инстанциясы менен Stream.builder() ыкмасын колдонуп агым түзүңүз
Биз ошондой эле Stream Builderди куруучунун дизайн үлгүсүн колдонуп агым түзүү үчүн колдоно алабыз . Ал an objectилерди этап-этабы менен курууга арналган. Келгиле, Stream Builder аркылуу агымды кантип түзө аларыбызды карап көрөлү .Stream.Builder<Integer> numBuilder = Stream.builder();
numBuilder.add(1).add(2).add( 3);
Stream<Integer> numStream = numBuilder.build();
Бул codeду колдонуу менен, сиз int элементтерин камтыган numStream аттуу агым түзө аласыз . Биринчи түзүлгөн numBuilder деп аталган Stream.Builder инстанциясынын аркасында баары тез жасалат .
3. Stream.of() ыкмасын колдонуп, көрсөтүлгөн маанилер менен агым түзүңүз
Агымды түзүүнүн дагы бир жолу Stream.of() ыкмасын колдонууну камтыйт . Бул берилген баалуулуктар менен агымды түзүүнүн жөнөкөй жолу. Ал жарыялайт жана ошондой эле жипти инициализациялайт. Агымды түзүү үчүн Stream.of() ыкмасын колдонуунун мисалы:Stream<Integer> numStream = Stream.of(1, 2, 3);
Бул code Stream.Builder аркылуу мурунку ыкмада жасагандай, int элементтерин камтыган агымды түзөт . Бул жерде биз Stream.of() аркылуу алдын ала аныкталган маанилер менен түз агым түздүк [1, 2 жана 3] .
4. Arrays.stream() ыкмасын колдонуп, учурдагы массивден агым түзүңүз
Жипти түзүүнүн дагы бир кеңири таралган ыкмасы Java'да массивдерди колдонууну камтыйт. Бул жердеги агым Arrays.stream() ыкмасын колдонуу менен учурдагы массивден түзүлөт . Бардык массив элементтери агымдык элементтерге айландырылат. Бул жерде жакшы мисал:Integer[] arr = {1, 2, 3, 4, 5};
Stream<Integer> numStream = Arrays.stream(arr);
Бул code бүтүн сан болгон arr деп аталган массивдин мазмунун камтыган numStreamди жаратат .
5. Stream.concat() ыкмасын колдонуу менен учурдагы эки агымды бириктирүү
Агымды түзүү үчүн колдонула турган дагы бир ыкма Stream.concat() ыкмасы болуп саналат . Ал бир жипти түзүү үчүн эки жипти бириктирүү үчүн колдонулат. Эки агым тең тартипте бириктирилген. Бул биринчи жип биринчи келет дегенди билдирет, андан кийин экинчи жип ж.б.у.с. Мындай бириктирүүнүн мисалы мындай көрүнөт:Stream<Integer> numStream1 = Stream.of(1, 2, 3, 4, 5);
Stream<Integer> numStream2 = Stream.of(1, 2, 3);
Stream<Integer> combinedStream = Stream.concat( numStream1, numStream2);
Жогорудагы билдирүү биринчи агым numStream1 жана экинчи агым numStream2 бирден элементтерин камтыган combinedStream аттуу акыркы агымды түзөт .
Java Stream менен операциялардын түрлөрү
Жогоруда айтылгандай, сиз Java 8де Java Stream менен операциялардын эки түрүн аткара аласыз: орто жана терминал. Келгиле, алардын ар бирин кененирээк карап көрөлү.Аралык операциялар
Аралык операциялар чыгаруу агымын жаратат жана терминалдык операцияга туш болгондо гана аткарылат. Бул ортодогу операциялар жалкоолук менен аткарылып, трубопровод менен өткөрүлөт жана терминалдык операция менен гана бүтүшү мүмкүн дегенди билдирет. Жалкоо баалоо жана түтүктөрдү түзүү жөнүндө бир аз кийинчерээк билесиз. Аралык операцияларга төмөнкү ыкмалар мисал боло алат: filter() , map() , different() , peek() , sorted() жана башкалар.Терминалдык операциялар
Терминал операциялары аралык операциялардын аткарылышын аяктайт, ошондой эле чыгаруу агымынын акыркы натыйжаларын кайтарат. Терминалдык операциялар жалкоолук менен аткаруунун бүтүшүн билдиргендиктен, бул жипти терминалдык операциядан өткөндөн кийин кайра колдонууга болбойт. Терминалдык операциялардын мисалдары төмөнкүдөй ыкмалар: forEach() , collect() , count() , reduce() ж.б.Java Stream менен операциялардын мисалдары
Аралык операциялар
Бул жерде Java агымына колдонула турган кээ бир ортодогу операциялардын айрым мисалдары келтирилген:filter()
Бул ыкма Javaдагы белгилүү бир предикатка дал келген агымдын элементтерин чыпкалоо үчүн колдонулат. Бул чыпкаланган элементтер андан кийин жаңы агымды түзөт. Жакшыраак түшүнүү үчүн бир мисалды карап көрөлү.Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> even = numStream.filter(n -> n % 2 == 0) .collect(Collectors.toList()); System.out.println(even);
Жыйынтык:
карта()
Бул ыкма баштапкы киргизүү агымынын элементтеринде карталанган функцияларды аткаруу менен жаңы агымды түзүү үчүн колдонулат. Балким, жаңы агымда башка маалымат түрү бар. Мисал мындай көрүнөт:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> d = numStream.map(n -> n*2) .collect(Collectors.toList()); System.out.println(d);
Жыйынтык:
distinct()
Бул ыкма дубликаттарды чыпкалоо аркылуу агымдагы айрым элементтерди гана алуу үчүн колдонулат. Ошол эле мисал мындай көрүнөт:Stream<Integer> numStream = Stream.of(43,65,1,98,63,63,1); List<Integer> numList = numStream.distinct() .collect(Collectors.toList()); System.out.println(numList);
Жыйынтык:
peek()
Бул ыкма терминалдык операцияны аткаруудан мурун аралык өзгөрүүлөргө көз салуу үчүн колдонулат. Бул агымдын ар бир элементи боюнча операцияны аткаруу үчүн peek() колдонулушу мүмкүн дегенди билдирет, анда андан аркы аралык операциялар аткарыла турган агым түзүү.Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> nList = numStream.map(n -> n*10) .peek(n->System.out.println("Mapped: "+ n)) .collect(Collectors.toList()); System.out.println(nList);
Жыйынтык:
сорттолгон()
Sorted() ыкмасы агымдын элементтерин сорттоо үчүн колдонулат. Демейки боюнча, ал элементтерди өсүү тартибинде иреттейт. Сиз ошондой эле параметр катары белгилүү бир сорттоо тартибин көрсөтө аласыз. Бул ыкманы ишке ашыруунун мисалы мындай көрүнөт:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); numStream.sorted().forEach(n -> System.out.println(n));
Жыйынтык:
Терминалдык операциялар
Бул жерде Java агымдарына колдонула турган кээ бир терминалдык операциялардын айрым мисалдары келтирилген:ар бирине()
forEach() методу агымдын бардык элементтерин кайталоо жана функцияны ар бир элементте бирден аткаруу үчүн колдонулат. Бул for , while жана башкалар сыяктуу цикл операторлоруна альтернатива катары иштейт . Мисал:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); numStream.forEach(n -> System.out.println(n));
Жыйынтык:
count()
count() ыкмасы агымдагы элементтердин жалпы санын алуу үчүн колдонулат. Бул коллекциядагы элементтердин жалпы санын аныктоо үчүн көбүнчө колдонулган size() ыкмасына окшош . Java Stream менен count() ыкмасын колдонуунун мисалы төмөнкүдөй:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); System.out.println(numStream.count());
Жыйынтык:
чогултуу()
collect() методу агым элементтеринин өзгөрүлмө кыскартууларын аткаруу үчүн колдонулат. Аны иштетип бүткөндөн кийин агымдан мазмунду алып салуу үчүн колдонсо болот. Ал кыскартууларды аткаруу үчүн Коллектор классын колдонот .Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); List<Integer> odd = numStream.filter(n -> n % 2 == 1) .collect(Collectors.toList()); System.out.println(odd);
Жыйынтык:
min() жана макс()
min() ыкмасы , аты айтып тургандай, агымдагы минималдуу элементти табуу үчүн колдонулушу мүмкүн. Ошо сыяктуу эле, max() ыкмасы агымдагы максималдуу элементти табуу үчүн колдонулушу мүмкүн. Келгиле, аларды бир мисал менен кантип колдонсо болорун түшүнүүгө аракет кылалы:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); int smallest = numStream.min((m, n) -> Integer.compare(m, n)).get(); System.out.println("Smallest element: " + smallest);
numStream = Stream.of(43, 65, 1, 98, 63); int largest = numStream.max((m, n) -> Integer.compare(m, n)).get(); System.out.println("Largest element: " + largest);
Жыйынтык:
findAny() жана findFirst()
findAny() агымдын каалаган элементин Кошумча катары кайтарат . Эгерде агым бош болсо, ал дагы Кошумча маанини кайтарат , ал бош болот. findFirst() агымдын биринчи элементин Кошумча катары кайтарат . findAny() методундагыдай эле , findFirst() методу да тиешелүү агым бош болсо, бош Кошумча параметрди кайтарат. Бул ыкмалардын негизинде төмөнкү мисалды карап көрөлү:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); Optional<Integer> opt = numStream.findFirst();System.out.println(opt); numStream = Stream.empty(); opt = numStream.findAny();System.out.println(opt);
Жыйынтык:
allMatch() , anyMatch() жана noneMatch()
allMatch() методу агымдагы бардык элементтердин белгилүү бир предикатка дал келгендигин текшерүү үчүн колдонулат жана эгер туура келсе логикалык маанини true кайтарат, антпесе false кайтарат . Эгерде агым бош болсо, анда ал чындыкты кайтарат . anyMatch() методу агымдагы элементтердин кайсынысы болбосун белгилүү бир предикатка дал келгенин текшерүү үчүн колдонулат. Ал эгер чын болсо, анда жалган деп кайтарат . Эгерде агым бош болсо, ал false кайтарат . noneMatch() методу агымдагы эч бир элемент предикатка дал келбесе чындыкты кайтарат , ал эми башка учурда false . Муну көрсөтүү үчүн бир мисал мындай көрүнөт:Stream<Integer> numStream = Stream.of(43, 65, 1, 98, 63); boolean flag = numStream.allMatch(n -> n1); System.out.println(flag); numStream = Stream.of(43, 65, 1, 98, 63); flag = numStream.anyMatch(n -> n1); System.out.println(flag); numStream = Stream.of(43, 65, 1, 98, 63); flag = numStream.noneMatch(n -> n==1);System.out.println(flag);
Жыйынтык:
Java агымындагы жалкоо баалоо
Жалкоо баалоо Java 8деги Java Streams менен иштөөдө оптималдаштырууга алып келет. Алар негизинен терминалдык операция жолукканга чейин аралык операцияларды кечиктирүүнү камтыйт. Жалкоо баалоо натыйжа чындап керек болгонго чейин эсептөөлөр боюнча ресурстардын ашыкча ысырап болушуна жол бербөө үчүн жооп берет. Аралык операциялардан келип чыккан чыгаруу агымы терминалдык операция аяктагандан кийин гана түзүлөт. Lazy баалоо Java агымындагы бардык орто операциялар менен иштейт. Жалкоо баалоону абдан пайдалуу колдонуу чексиз агымдар менен иштөөдө пайда болот. Бул жол менен, көп керексиз иштетүүнүн алдын алат.Java агымындагы түтүктөр
Java агымындагы куур биринин артынан бири тизилген кириш агымынан, нөл же андан көп аралык операциялардан жана акырында терминалдык операциядан турат. Java агымдарында аралык операциялар жалкоолук менен аткарылат. Бул түтүкчөлөр аралык операцияларды сөзсүз кылат. Негизинен ирети менен бириктирилген аралык операциялар болгон түтүк өткөргүчтөрү менен жалкоолук менен аткаруу мүмкүн болот. Түтүк өткөргүчтөр терминалдык операция жолуккандан кийин аткарылышы керек болгон аралык операцияларды көзөмөлдөөгө жардам берет.Корутунду
Эми бүгүн эмнени үйрөнгөнүбүздү жыйынтыктайлы. Бул макалада:- Биз Java Streams деген эмне экенин тез карап чыктык.
- Андан кийин биз Java 8де Java жиптерин түзүүнүн көптөгөн ар кандай ыкмаларын үйрөндүк.
- Биз Java агымдарында аткарыла турган операциялардын эки негизги түрүн (аралык операциялар жана терминалдык операциялар) үйрөндүк.
- Андан кийин биз орто жана терминалдык операциялардын бир нече мисалдарын деталдуу карап чыктык.
- Биз жалкоо баалоо жөнүндө көбүрөөк билдик жана акырында Java жиптериндеги куурларды үйрөндүк.
GO TO FULL VERSION