English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
أضافت API Java 8抽象 جديدة تُدعى Stream، تتيح لك معالجة البيانات بطريقة تعريفية.
يقدم Stream استخدام طريقة بسيطة ومباشرة تشبه استخدام جملة SQL لاستعلام قاعدة بيانات لتقديم مستوى عالٍ من التعبير والعمليات على مجموعات Java.
يُمكن لـ API Stream زيادة إنتاجية مطوري Java بشكل كبير، مما يسمح لهم بكتابة كود فعال، نظيف، وسهل.
يُعتبر هذا النمط مجموعة العناصر التي سيتم معالجتها كنوع من تدفق، ينتقل عبر الأنابيب ويمكن معالجته في عقد الأنابيب، مثل التصفية، والترتيب، والجمع وما إلى ذلك.
الإлементات تتدفق في الأنابيب وتخضع للمعالجة من خلال العمليات المتوسطة (العمليات المتوسطة) للحصول على النتيجة النهائية من العمليات النهائية (العمليات النهائية).
+--------------------+ +------+ +------+ +---+ +-------+ | stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect| +--------------------+ +------+ +------+ +---+ +-------+
تحويل العملية السابقة إلى كود Java كالتالي:
List<Integer> transactionsIds = widgets.stream() .filter(b -> b.getColor() == RED) .sorted((x,y) -> x.getWeight() - y.getWeight()) .mapToInt(Widget::getWeight) .sum();
Stream (التدفق) هو قائمة عناصر تأتي من مصدر بيانات وتدعم العمليات التجميعية
قائمة العناصر المكونات هي كائنات معينة النوع، تشكل قائمة. لا يخزن Stream العناصر، بل يحسبها عند الطلب.
مصدر البيانات مصدر التدفق. يمكن أن يكون جمعية، مصفوفة، قناة I/O، مولد (generator) إلخ.
عمليات تجميع عمليات تجميع مشابهة لجمل SQL مثل filter، map، reduce، find، match، sorted إلخ.
وعلى عكس عمليات Collection السابقة، تشمل عمليات Stream خصائص أساسية إضافيتين:
الخط التسلسلي: كل العمليات الوسيطة تعود بتحويل التدفق نفسه. يمكن ربط عدة عمليات معًا لتكوين قناة مثل أسلوب التدفق (fluent style). يمكن لهذا القيام بتحسين العمليات مثل التأخير (laziness) والاختصار (short-circuiting).
التركيب الداخلي∶ كان تمرير الجمعيات دائمًا من خلال Iterator أو For-Each بطريقة واضحة خارج الجمعية، هذا يُدعى التكرار الخارجي. يقدم Stream طريقة تكرار داخلي، من خلال نموذج الزائر (Visitor)。
في Java 8، واجهات الجمعيات تحتوي على طريقتين لإنشاء التدفق:
stream() − إنشاء تدفق متسلسل للجمعية.
parallelStream() − إنشاء تدفق متوازٍ للجمعية.
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
Stream يقدم طريقة جديدة تُدعى 'forEach' لتكرار كل بيانات التدفق. الفقرة التالية من الكود تستخدم forEach للإخراج 10 أرقام عشوائية:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map 方法用于映射每个元素到对应的结果,以下代码片段使用 map 输出了元素对应的平方数:
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // 获取对应的平方数 List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
filter 方法用于通过设置的条件过滤出元素。以下代码片段使用 filter 方法过滤出空字符串:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); // 获取空字符串的数量 long count = strings.stream().filter(string -> string.isEmpty()).count();
limit 方法用于获取指定数量的流。以下代码片段使用 limit 方法打印出 10 条数据:
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted 方法用于对流进行排序。以下代码片段使用 sorted 方法对输出的 10 个随机数进行排序:
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
parallelStream 是流并行处理程序的代替方法。以下示例我们使用 parallelStream 来输出空字符串的数量:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); // 获取空字符串的数量 long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
我们可以很容易地在顺序运行和并行直接切换。
Collectors 类实现了很多归约操作,例如将流转换成集合和聚合元素。Collectors 可用于返回列表或字符串:
List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd", "", "jkl"); List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList()); System.out.println("قائمة المرشحين: " + filtered); String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("دمج الأنماط: "+ mergedString);
بالإضافة إلى ذلك، بعض مستويات التجميع التي تنتج نتائج الإحصاءات تكون مفيدة جدًا. إنها تستخدم بشكل رئيسي في الأنواع الأساسية مثل int،double،long،ويمكن استخدامها لإنشاء نتائج إحصائية مشابهة للآتي.
List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); IntSummaryStatistics stats = numbers.stream().mapToInt((x) -> x).summaryStatistics(); System.out.println("أكبر عدد في القائمة: "+ stats.getMax()); System.out.println("أصغر عدد في القائمة: "+ stats.getMin()); System.out.println("مجموع جميع الأعداد: "+ stats.getSum()); System.out.println("العدد المتوسط: "+ stats.getAverage());
ضع التالي في ملف Java8Tester.java:
import java.util.ArrayList; import java.util.Arrays; import java.util.IntSummaryStatistics; import java.util.List; import java.util.Random; import java.util.stream.Collectors; import java.util.Map; public class Java8Tester { public static void main(String args[]){ System.out.println("استخدام Java 7: "); // حساب الحروف الفارغة List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl"); System.out.println("القائمة: " + strings); long count = getCountEmptyStringUsingJava7(strings); System.out.println("عدد الحروف الفارغة: " + count); count = getCountLength2UsingJava7(strings); System.out.println("عدد الأعداد التي طولها 3: "+ count); // إزالة الأنماط الفارغة List<String> filtered = deleteEmptyStringsUsingJava7(strings); System.out.println("القائمة بعد الفيلتر: "+ filtered); // إزالة الأنماط الفارغة واستخدام المسافات بينها String mergedString = getMergedStringUsingJava7(strings,", "); System.out.println("دمج الأنماط: "+ mergedString); List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); // الحصول على أرقام مربعة عناصر القائمة List<Integer> squaresList = getSquares(numbers); System.out.println("قائمة الأعداد المربعة: " + squaresList); List<Integer> integers = Arrays.asList(1,2,13,4,15,6,17,8,19); System.out.println("القائمة: "+integers); System.out.println("أكبر عدد في القائمة: " + getMax(integers)); System.out.println("أصغر عدد في القائمة: " + getMin(integers)); System.out.println("إجمالي جميع الأرقام: " + getSum(integers)); System.out.println("متوسط القيمة: " + getAverage(integers)); System.out.println("عدد عشوائي: "); // إنتاج 10 أرقام عشوائية Random random = new Random(); for(int i=0; i < 10; i++){ System.out.println(random.nextInt()); } System.out.println("استخدام Java 8: "); System.out.println("القائمة: " + strings); count = strings.stream().filter(string->string.isEmpty()).count(); System.out.println("عدد الأنماط الفارغة: " + count); count = strings.stream().filter(string -> string.length() == 3).count(); System.out.println("عدد الأعداد التي طولها 3: "+ count); filtered = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.toList()); System.out.println("القائمة بعد الفيلتر: "+ filtered); mergedString = strings.stream().filter(string ->!string.isEmpty()).collect(Collectors.joining(", ")); System.out.println("دمج الأنماط: "+ mergedString); squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList()); System.out.println("قائمة المربعات: "+ squaresList); System.out.println("القائمة: "+integers); IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics(); System.out.println("أكبر عدد في القائمة: "+ stats.getMax()); System.out.println("أصغر عدد في القائمة: "+ stats.getMin()); System.out.println("مجموع جميع الأعداد: "+ stats.getSum()); System.out.println("العدد المتوسط: "+ stats.getAverage()); System.out.println("عدد عشوائي: "); random.ints().limit(10).sorted().forEach(System.out::println); // معالجة متوازية عدد = strings.parallelStream().filter(string -> string.isEmpty()).count(); System.out.println("空字符串的数量为: " + count); } private static int getCountEmptyStringUsingJava7(List<String> strings){ int count = 0; for(String string: strings){ if(string.isEmpty()){ count++; } } return count; } private static int getCountLength2UsingJava7(List<String> strings){ int count = 0; for(String string: strings){ if(string.length() == 3){ count++; } } return count; } private static List<String> deleteEmptyStringsUsingJava7(List<String> strings){ List<String> filteredList = new ArrayList<String>(); for(String string: strings){ if(!string.isEmpty()){ filteredList.add(string); } } return filteredList; } private static String getMergedStringUsingJava7(List<String> strings, String separator){ StringBuilder stringBuilder = new StringBuilder(); for(String string: strings){ if(!string.isEmpty()){ stringBuilder.append(string); stringBuilder.append(separator); } } String mergedString = stringBuilder.toString(); return mergedString.substring(0, mergedString.length()-2); } private static List<Integer> getSquares(List<Integer> numbers){ List<Integer> squaresList = new ArrayList<Integer>(); for(Integer number: numbers){ Integer square = new Integer(number.intValue() * number.intValue()); if(!squaresList.contains(square)){ squaresList.add(square); } } return squaresList; } private static int getMax(List<Integer> numbers){ int max = numbers.get(0); for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i); if(number.intValue() > max){ max = number.intValue(); } } return max; } private static int getMin(List<Integer> numbers){ int min = numbers.get(0); for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i); if(number.intValue() < min){ min = number.intValue(); } } return min; } private static int getSum(List numbers){ int sum = (int)(numbers.get(0)); for(int i=1; i < numbers.size(); i++){ sum += (int)numbers.get(i); } return sum; } private static int getAverage(List<Integer> numbers){ return getSum(numbers) / numbers.size(); } }
إذا قمت بتشغيل السكربت أعلاه، النتيجة ستكون:
$ javac Java8Tester.java $ java Java8Tester استخدام Java 7: القائمة: [abc, , bc, efg, abcd, , jkl] عدد الرموز الفارغة: 2 عدد الأنماط الطولها 3: 3 القائمة بعد الفلترة: [abc, bc, efg, abcd, jkl] دمج الأنماط: abc, bc, efg, abcd, jkl قائمة الأرقام المربعة: [9, 4, 49, 25] القائمة: [1, 2, 13, 4, 15, 6, 17, 8, 19] أكبر عدد في القائمة: 19 أصغر عدد في القائمة: 1 إجمالي جميع الأرقام: 85 متوسط : 9 رقم العشوائية: -393170844 -963842252 447036679 -1043163142 -881079698 221586850 -1101570113 576190039 -1045184578 1647841045 استخدام Java 8: القائمة: [abc, , bc, efg, abcd, , jkl] عدد الأنماط الفارغة: 2 عدد الأنماط الطولها 3: 3 القائمة بعد الفلترة: [abc, bc, efg, abcd, jkl] دمج الأنماط: abc, bc, efg, abcd, jkl قائمة مربعات: [9, 4, 49, 25] القائمة: [1, 2, 13, 4, 15, 6, 17, 8, 19] أكبر عدد في القائمة: 19 أصغر عدد في القائمة: 1 إجمالي جميع الأرقام: 85 العدد المتوسط: 9.444444444444445 رقم العشوائية: -1743813696 -1301974944 -1299484995 -779981186 136544902 555792023 1243315896 1264920849 1472077135 1706423674 عدد الأنماط الفارغة: 2