مشخصات مقاله
-
695
-
0.0
-
5454
-
0
-
0
Stream یا جریان ها در Java 8
Stream ها یا جریان ها در Java 8
Stream لایه ی انتزاعی جدیدی است که در Java 8 معرفی شده است. با استفاده از Stream می توانید داده ها را به صورت اعلانی و شبیه به دستورات SQL پردازش کنید. برای مثال دستور SQL زیر را در نظر بگیرید.
SELECT max(salary), employee_id, employee_name FROM Employee
این عبارت به صورت خودکار، جزئیات کارمندی که بیشترین حقوق را گرفته است را برگشت می دهد، بدون این که در سمت برنامه نویس محاسبه ای انجام شود. برای استفاده از فریمورک اجتماع در Java برنامه نویس باید از حلقه ها استفاده کند و بررسی هایی را به صورت مکرر ایجاد کند. یکی از نگرانی های دیگر بازدهی است؛ چرا که پردازنده های چند هسته ای به راحتی در دسترس هستند و برنامه نویس Java باید پردازش کد را به صورت موازی بنویسد که این خود احتمال خطا را افزایش می دهد.
جهت حل این مشکلات Java 8 مفهوم Stream را معرفی کرده است. این مفهوم به برنامه نویس اجازه می دهد تا به صورت اعلانی داده ها را پردازش کند و بدون نیاز به نوشتن هیچ کد خاصی برای آن معماری چند هسته ای را ممکن سازد.
Stream چیست؟
Stream به دنباله ای از اشیاء از یک منبع گفته می شود که عملیات های تجمعی را تقویت می کند. در ادامه ویژگی های Stream ها را می توانید مشاهده کنید.
- دنباله ی عناصر: Stream مجموعه ای از عناصر با نوع مشخص را به صورت دنباله ای ارائه می کند. Stream ها عناصر را در صورت نیاز دریافت کرده آن ها را محاسبه می کنند و هیچوقت آن ها را ذخیره نمی کنند.
- منبع: Stream ها اجتماع ها، آرایه ها یا منابع ورودی / خروجی را به عنوان منبع ورودی دریافت می کنند.
- عملیات های تجمعی: Stream از عملیات های تجمعی پستیبانی می کند؛ مثل فیلتر، نگاشت، حد، کاهش، یافتن، تطبیق دادن و ... .
- پایپلاینینگ: بسیاری از عملیات های Stream خود Stream را برگشت می دهند تا بتوان نتیجه ی آن ها را پایپلاین کرد. به این عملیات ها، عملیات های آنی گفته می شود و کار آن ها گرفتن ورودی، پردازش آن و برگرداندن خروجی به هدف است. متد collect() عملیات ترمینالی است که معمولا در انتهای عملیات پایپلاینینگ حضور دارد تا پایان Stream را مشخص کند.
- تکرارهای خودکار: عملیات های Stream تکرار را به صورت داخلی بر روی عناصر منبع انجام می دهند. برخلاف کلکسیون ها (اجتماع ها) که تکرار صریح در آن ها نیاز است.
تولید Stream ها
در Java 8 رابط کلکسیون جهت تولید یک Stream دو متد در اختیار دارد.
- stream(): با در نظر گرفتن کلکسیون به عنوان منبع خود، یک Stream دنباله ای را برگشت می دهد.
- parallelStream() : با در نظر گرفتن کلکسیون به عنوان منبع خود، یک Stream موازی را برگشت می دهد.
List< String > strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
List< String > filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
forEach در Java 8
Stream جهت تکرار هر یک از عناصر خود متد جدید ‘forEach’ را فراهم می کند. در کد زیر چگونگی چاپ 10 عدد تصادفی با استفاده از forEach نشان داده شده است.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
map در Java 8
جهت نگاشت هر یک از عناصر به نتیجه ی مربوط به خود از متد ‘map’ استفاده می شود. در کد زیر مربعات منحصر به فرد اعداد با استفاده از این متد نشان داده شده اند.
List< Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5); //get list of unique squares List< Integer> squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
آموزش فیلتر در Java 8
جهت حذف عناصر بر اساس یکی از معیارها از متد ‘filter’ استفاده می شود. در کد زیر تعداد رشته های خالی با استفاده از این متد چاپ می شود.
List< String >strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.stream().filter(string - > string.isEmpty()).count();
حد در Java 8
جهت کاهش اندازه ی Stream از متد ‘limit’ استفاده می شود. در کد زیر چگونگی چاپ 10 عدد تصادفی با استفاده از limit نشان داده شده است.
Random random = new Random(); random.ints().limit(10).forEach(System.out::println);
sorted در Java 8
جهت مرتب کردن Stream از متد ‘sorted’ استفاده می شود. در کد زیر چگونگی چاپ 10 عدد تصادفی به صورت مرتب نشان داده شده است.
Random random = new Random(); random.ints().limit(10).sorted().forEach(System.out::println);
پردازش موازی در Java 8
parallelStream یکی از راهکارهای پردازش موازی در Stream است. به تکه کد زیر نگاهی بیاندازید. در این کد تعداد رشته های خالی با استفاده از parallelStream چاپ می شود.
List< String > strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
//get count of empty string
int count = strings.parallelStream().filter(string -> string.isEmpty()).count();
سوییچ کردن بین Stream های موازی و دنباله ای آسان است.
کالکتورها در Java 8
جهت ترکیب نتیجه ی پردازش انجام شده بر روی عناصر یک Stream از کالکتورها استفاده می شود. از کالکتورها می توان جهت برگشت دادن یک لیست یا یک رشته استفاده کرد.
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 List: " + filtered);
String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
Statistics در Java 8
جهت محاسبه ی تمامی اطلاعات آماری در زمان پردازش Stream از گردآورندگان آماری در Java 8 استفاده می شود.
List numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
IntSummaryStatistics stats = integers.stream().mapToInt((x) -> x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());
System.out.println("Lowest number in List : " + stats.getMin());
System.out.println("Sum of all numbers : " + stats.getSum());
System.out.println("Average of all numbers : " + stats.getAverage());
نمونه ای برای Stream در Java 8
با استفاده از یکی از ویرایشگرهای مورد نظر خود، برنامه ی Javaی زیر را مثلا در C:\> JAVA ایجاد کنید.
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("Using Java 7: ");
// Count empty strings
List< String > strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
System.out.println("List: " +strings);
long count = getCountEmptyStringUsingJava7(strings);
System.out.println("Empty Strings: " + count);
count = getCountLength3UsingJava7(strings);
System.out.println("Strings of length 3: " + count);
//Eliminate empty string
List< String > filtered = deleteEmptyStringsUsingJava7(strings);
System.out.println("Filtered List: " + filtered);
//Eliminate empty string and join using comma.
String mergedString = getMergedStringUsingJava7(strings,", ");
System.out.println("Merged String: " + mergedString);
List< Integer > numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
//get list of square of distinct numbers
List< Integer > squaresList = getSquares(numbers);
System.out.println("Squares List: " + squaresList);
List< Integer > integers = Arrays.asList(1,2,13,4,15,6,17,8,19);
System.out.println("List: " +integers);
System.out.println("Highest number in List : " + getMax(integers));
System.out.println("Lowest number in List : " + getMin(integers));
System.out.println("Sum of all numbers : " + getSum(integers));
System.out.println("Average of all numbers : " + getAverage(integers));
System.out.println("Random Numbers: ");
//print ten random numbers
Random random = new Random();
for(int i = 0; i < 10; i++) {
System.out.println(random.nextInt());
}
System.out.println("Using Java 8: ");
System.out.println("List: " +strings);
count = strings.stream().filter(string- >string.isEmpty()).count();
System.out.println("Empty Strings: " + count);
count = strings.stream().filter(string - > string.length() == 3).count();
System.out.println("Strings of length 3: " + count);
filtered = strings.stream().filter(string - >!string.isEmpty()).collect(Collectors.toList());
System.out.println("Filtered List: " + filtered);
mergedString = strings.stream().filter(string - >!string.isEmpty()).collect(Collectors.joining(", "));
System.out.println("Merged String: " + mergedString);
squaresList = numbers.stream().map( i - >i*i).distinct().collect(Collectors.toList());
System.out.println("Squares List: " + squaresList);
System.out.println("List: " +integers);
IntSummaryStatistics stats = integers.stream().mapToInt((x) - >x).summaryStatistics();
System.out.println("Highest number in List : " + stats.getMax());
System.out.println("Lowest number in List : " + stats.getMin());
System.out.println("Sum of all numbers : " + stats.getSum());
System.out.println("Average of all numbers : " + stats.getAverage());
System.out.println("Random Numbers: ");
random.ints().limit(10).sorted().forEach(System.out::println);
//parallel processing
count = strings.parallelStream().filter(string - > string.isEmpty()).count();
System.out.println("Empty Strings: " + count);
}
private static int getCountEmptyStringUsingJava7(List< String > strings) {
int count = 0;
for(String string: strings) {
if(string.isEmpty()) {
count++;
}
}
return count;
}
private static int getCountLength3UsingJava7(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 مانند زیر این کلاس را کامپایل کنید.
C:\JAVA>javac Java8Tester.java
حالا مانند زیر Java8Tester را اجرا کنید.
C:\JAVA>java Java8Tester
نتیجه باید به صورت زیر نمایش داده شود.
Using Java 7: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9 Random Numbers: -1279735475 903418352 -1133928044 -1571118911 628530462 18407523 -881538250 -718932165 270259229 421676854 Using Java 8: List: [abc, , bc, efg, abcd, , jkl] Empty Strings: 2 Strings of length 3: 3 Filtered List: [abc, bc, efg, abcd, jkl] Merged String: abc, bc, efg, abcd, jkl Squares List: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Highest number in List : 19 Lowest number in List : 1 Sum of all numbers : 85 Average of all numbers : 9.444444444444445 Random Numbers: -1009474951 -551240647 -2484714 181614550 933444268 1227850416 1579250773 1627454872 1683033687 1798939493 Empty Strings: 2
برای مطالعه سرفصل آموزش جاوا (J2SE) کلیک نمایید .