ما هو Stream API؟
تعد Stream API طريقة جديدة للعمل مع بنيات البيانات بأسلوب وظيفي. Stream An API (وصف للطرق التي يمكن لبرنامج كمبيوتر واحد من خلالها التواصل مع برنامج آخر) هو في جوهره تدفق من البيانات. مصطلح "خيط" في حد ذاته غامض تمامًا في البرمجة بشكل عام وفي Java بشكل خاص.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)
يقوم بتصفية الدفق، ويمرر فقط تلك العناصر التي تجتاز الشرط (المسند هو واجهة وظيفية مضمنة تضاف إلى الحزمة في 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));
-
تخطي (طويل ن) - تخطي عناصر ن:
stream.skip(3).forEach(x -> System.out.println(x));
-
مرتبة()
- فرز (مقارنة المقارنة) - فرز الدفق (الفرز مثل TreeMap):
stream.sorted().forEach(x -> System.out.println(x));
-
متميز () - يتحقق من تفرد العناصر في الدفق (يزيل تكرار العناصر) ؛
-
dropWhile (المسند المسند) - يتخطى العناصر التي تستوفي الشرط (ظهر في Java 9، تتحقق الواجهة الوظيفية Predicate<T> من استيفاء بعض الشروط. إذا تم استيفائه، فسيتم إرجاع true. يأخذ تعبير lambda كائنًا من النوع T كمعلمة:
Predicate<Integer> isPositive = x -> x > 0; System.out.println(isPositive.test(3)); // true System.out.println(isPositive.test(-9)); // false
-
forEach(إجراء المستهلك) - مشابه لكل (المستهلك<T> ينفذ بعض الإجراءات على كائن من النوع T دون إرجاع أي شيء)؛
-
count() – يُرجع عدد عناصر الدفق:
System.out.println(stream.count());
-
Collect (جامع المجمع) - الأسلوب يجمع كل العناصر في قائمة أو مجموعة أو مجموعة أخرى، ويجمع العناصر وفقًا لبعض المعايير، ويجمع كل شيء في سلسلة، وما إلى ذلك:
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) - يحول جميع عناصر الدفق إلى كائن واحد (احسب مجموع كل العناصر، أو ابحث عن الحد الأدنى للعنصر)، أولاً
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)
يبحث الحد الأقصى الاختياري (Comparator comparator) عن الحد الأدنى/الحد الأقصى للعنصر بناءً على المقارنة التي تم تمريرها؛ -
findFirst()
- يسحب العنصر الأول من الدفق:Stream.of(1, 2, 3, 4, 9).findFirst();
-
allMatch(Predicate predicate)
- يُرجع صحيحًا إذا كانت جميع عناصر الدفق تستوفي الشرط. إذا تمت مواجهة أي عنصر وكانت نتيجة استدعاء الدالة الأصلية خاطئة ، فسيتوقف المشغل عن فحص العناصر ويعيد خطأ :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)
- جامع يقوم بتحويل الكائنات إلى int/long/double ويحسب المجموع.
GO TO FULL VERSION