سری مطالب آموزش جاوا 8 – بخش ششم Streams
کلاس Stream یک لایه انتزاعی جدید است که در جاوا 8 معرفی شده است. با استفاده از Stream میتوانید دادهها را بهصورت اعلانی شبیه به پرسوجوهای SQL پردازش کنید. برای مثال جمله SQL زیر را درنظر بگیرید:
SELECT max(salary), employee_id, employee_name FROM Employee
عبارت SQL فوق، بهطور خودکار حداکثر جزییات مربوط به حقوق کارمندان را برمیگرداند، بدون اینکه هیچ محاسبهای در سمت توسعهدهنده انجام دهد. با استفاده از مجموعهای فریمورکها در جاوا، یک توسعهدهنده مجبور است از حلقهها استفاده کند و چکهای مکرر انجام دهد. نگرانی دیگر کارایی است. ازآنجا که پردازندههای چندهستهای بهراحتی دردسترس هستند، یک توسعهدهنده جاوا مجبور است پردازش کد موازی بنویسد که بسیار مستعد داشتنِ خطاست.
برای برطرف کردن چنین مواردی، جاوا 8 مفهوم Stream را معرفی کرد که به توسعهدهنده امکان میدهد دادهها را بهصورت اعلانی پردازش کند و از معماری چندهستهای استفاده کند بدون اینکه نیاز به نوشتن کد خاصی برای آن باشد.
Stream چیست؟
Stream یک توالی از اشیاء از یک منبع را نشان میدهد که از مجموع عملیاتها پشتیبانی میکند. در زیر مشخصات و ویژگیهای یک Stream بیان شده است:
- توالی عناصر: یک Stream مجموعهای از عناصر از نوعی[1] را بهصورت سریالی بیان میکند. یک Stream بنابر تقاضا عناصر را میگیرد و محاسبه میکند. Stream هرگز عناصر را ذخیره نمیکند.
- منبع: Stream مجموعهها[2]، آرایهها یا منابع I / O[3] را بهعنوان منبع ورودی میگیرد.
- عملیاتهای مجموع[4]: Stream از عملیاتهای مجموع مانند filter، map، limit، reduce، find، match و غیره پشتیبانی میکند.
- خط لولهسازی[5]: بیشتر عملیات Stream خودش Stream برمیگرداند تا نتایج آنها را بشود خط لولهسازی کرد. این عملیاتها به نام عملیاتهای میانی نامیده میشوند و وظیفه آنها گرفتن ورودی، پردازش آن و برگرداندنِ خروجی به Target[6] است. متد collect() یک عملیات پایانه[7] است که معمولا در انتهای عملیات خط لولهسازی وجود دارد تا انتهای Stream را مشخص کند.
- تکرارهای خودکار[8]: عملیاتهای Stream تکرارهای داخلی (داخل کلاس) را بیش از عناصر منبع اعلام شده انجام میدهند، برخلاف مجموعهها که لازم است تکرارها اعلانی صریح داشته باشند.
تولید Stream ها
با جاوا 8، اینترفیس Collection دو متد دارد که تولید یک Stream میکند.
- متد Stream(): یک Stream سریالی را با در نظر گرفتن Collection بهعنوان منبع برمیگرداند.
- متد parallelStream(): یک Stream موازی را با درنظر گرفتن Collection بهعنوان منبع بازمیگرداند.
مثال:
List<String> strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,””, “jkl”);
List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
forEach
Stream یک متد forEach جدید برای تکرار روی هر عنصر Stream فراهم کرده است. تکه کد زیر نحوه چاپ تصادفی 10 عنصر را با استفاده از حلقه تکرار forEach نشان میدهد.
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
map
متد map برای نگاشت هر عنصر به نتیجه متناظرش استفاده میشود. تکه کد زیر با استفاده از متد 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());
Filter
متد filter برای ازبین بردن عناصر براساس یک معیار[9] استفاده میشود. تکه کد زیر با استفاده از متد filter تعدادی رشته[10] خالی چاپ میکند.
List<String>strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,””, “jkl”);
//get count of empty string
int count = strings.stream().filter(string -> string.isEmpty()).count();
limit
از متد limit برای کاهش اندازه Stream استفاده میشود. تکه کد زیر نحوه چاپ 10 عدد تصادفی را با استفاده از متد limit نمایش میدهد.
Random random = new Random();
random.ints().limit(10).forEach(System.out::println);
sorted
متد sorted برای مرتبسازی Stream مورد استفاده قرار میگیرد. تکه کد زیر نحوه نمایش چاپ 10 عدد تصادفی را بهشکل مرتبشده نشان میدهد.
Random random = new Random();
random.ints().limit(10).sorted().forEach(System.out::println);
پردازش موازی[11]
parallelStream یک Stream دیگر برای پردازش موازی است. به تکه کد زیر که تعدادی رشته خالی را با استفاده از parallelStream چاپ میکند نگاهی بیندازید.
List<String> strings = Arrays.asList(“abc”, “”, “bc”, “efg”, “abcd”,””, “jkl”);
//get count of empty string
long count = strings.parallelStream().filter(string -> string.isEmpty()).count();
جابجایی بین Streamهای موازی و متوالی بسیار آسان است.
بخشهای دیگر مقاله را از لینکهای زیر بخوانید:
سری مطالب آموزش جاوا ۸ – بخش ششم Streams (قسمت دوم)
[1] Type
[2] Collection
[3] Input / Output
[4] Aggregate
[5] Pipelining
[6] هدف
[7] Terminal
[8] Automatic Iterations
[9] Criteria
[10] String
[11] Parallel Processing