Stream API چیست؟
Stream API یک روش جدید برای کار با ساختارهای داده به سبک عملکردی است. جریان یک API (توضیح راه هایی که یک برنامه کامپیوتری می تواند با برنامه دیگر ارتباط برقرار کند) در هسته خود جریانی از داده است. خود اصطلاح "thread" در برنامه نویسی به طور کلی و در جاوا به طور خاص کاملاً مبهم است.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 به شما امکان می دهد تعداد خطوط کد را کاهش دهید. مثال با یک جریان:
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 - ایجاد یک شی
Stream
; - 13 - متد
filter
(فیلتر) - عملگر میانی،x
با یک عنصر از مجموعه برای شمارش برابر است (مانندfor each
) و بعد از -> نشان می دهیم که چگونه مجموعه ما فیلتر شده است و از آنجایی که این یک عملگر میانی است، مجموعه فیلتر شده به سمت بالاتر می رود. متدforEach
که به نوبه خود آنالوگ پایانی (نهایی) شمارش استfor each
(عبارتSystem.out::println
کوتاه برای:،x-> System.out.println(x))
که به نوبه خود از تمام عناصر مجموعه ارسال شده به آن عبور می کند و آن را نمایش می دهد)
- تا زمانی که اپراتور ترمینال فراخوانی نشود، پردازش آغاز نخواهد شد.
list.stream().filter(s -> s > 5)
(یک عنصر را از لیست نمی گیرد)؛ - یک نمونه از یک جریان را نمی توان بیش از یک بار استفاده کرد =( ;
بنابراین، هر بار که جدید است:
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 اضافه شده است.java.util.function
مقدار " درست " و " نادرست " را بررسی می کند).map(Function mapper)
امکان ایجاد تابعی را فراهم می کند که با آن هر عنصر را تغییر دهیم و از آن بگذریم (اینترفیس عملکردیFunction<T,R>
تابع انتقال از یک شی از نوع T به یک شی از نوع R را نشان می دهد)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) – skip n عنصر:
stream.skip(3).forEach(x -> System.out.println(x));
-
مرتب شده ()
- sorted (مقایسه کننده مقایسه) - جریان را مرتب می کند (مرتب سازی مانند TreeMap):
stream.sorted().forEach(x -> System.out.println(x));
-
distinct() - جریان را برای منحصر به فرد بودن عناصر بررسی می کند (تکرار عناصر را حذف می کند).
-
dropWhile (گزاره محمول) - از عناصری که شرط را برآورده می کنند (که در جاوا 9 ظاهر شد، رد می شود، رابط عملکردی Predicate<T> بررسی می کند که آیا برخی از شرایط برآورده شده است یا خیر. اگر برآورده شد، true برگردانده می شود. عبارت لامبدا یک شی از نوع را می گیرد. T به عنوان یک پارامتر:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach (کنش مصرف کننده) - مشابه برای هر (Consumer<T> برخی از عملکردها را روی یک شی از نوع T بدون برگرداندن چیزی انجام می دهد).
-
count() – تعداد عناصر جریان را برمیگرداند:
System.out.println(stream.count());
-
collect (Collector Collector) – متد همه عناصر را در یک لیست، مجموعه یا مجموعه دیگری جمع آوری می کند، عناصر را بر اساس معیاری گروه بندی می کند، همه چیز را در یک رشته ترکیب می کند و غیره:
List<String> list = Stream.of(“One”, “Two”, “Three”).collect(Collectors.toList());
-
collect(Supplier supplier, BiConsumer accumulator, BiConsumer combiner)
- مانند،collect(collector)
فقط پارامترها برای راحتی شکسته می شوند (supplier
اشیاء جدید (ظروف) را فراهم می کند، به عنوان مثالnew ArrayList()
،accumulator
یک عنصر را به ظرف اضافه می کند،combiner
بخش هایی از جریان را با هم ترکیب می کند). -
کاهش (هویت T، BinaryOperator accumulator) - تمام عناصر جریان را به یک شی تبدیل می کند (مجموع همه عناصر را محاسبه کنید، یا عنصر حداقل را پیدا کنید)، ابتدا شی
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)
حداکثر اختیاری (مقایسه کننده مقایسه) عنصر حداقل/حداکثر را بر اساس مقایسه کننده پاس شده جستجو می کند. -
findFirst()
– اولین عنصر جریان را بیرون می کشد:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
- اگر همه عناصر جریان شرط را برآورده کنند، مقدار true را برمی گرداند. اگر با عنصری مواجه شد که نتیجه فراخوانی تابع محمول نادرست باشد ، اپراتور اسکن عناصر را متوقف می کند و 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)
- اگر با گذراندن تمام عناصر جریان، هیچ یک از آنها شرایط را برآورده نکرده باشند، 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)
- کلکتوری که اشیا را به int/long/double تبدیل می کند و مجموع را محاسبه می کند.
GO TO FULL VERSION