پردازش داده ها با Java SE 8 جریان ، قسمت 1

ساخت وبلاگ

بدون مجموعه چه کاری انجام می دهید؟تقریباً هر برنامه جاوا مجموعه ها را می سازد و پردازش می کند. آنها برای بسیاری از کارهای برنامه نویسی اساسی هستند: آنها به شما امکان می دهند داده ها را گروه بندی و پردازش کنید. به عنوان مثال ، شما ممکن است بخواهید مجموعه ای از معاملات بانکی را برای بیان بیانیه مشتری ایجاد کنید. سپس ، ممکن است بخواهید کل مجموعه را پردازش کنید تا دریابید که مشتری چقدر پول خرج کرده است. علیرغم اهمیت آنها ، مجموعه های پردازش در جاوا بسیار مناسب نیستند.

  • در ابتدا در شماره مارس/آوریل 2014 مجله جاوا منتشر شده است. امروز مشترک شوید.

اول ، الگوهای پردازش معمولی در مجموعه ها شبیه به عملیات SQL مانند مانند "یافتن" است (برای مثال ، معامله را با بالاترین ارزش پیدا کنید) یا "گروه بندی" (به عنوان مثال ، گروه بندی تمام معاملات مربوط به خرید مواد غذایی). بیشتر بانکهای اطلاعاتی به شما امکان می دهند چنین عملیاتی را به صورت اعلامیه ای مشخص کنید. به عنوان مثال ، پرس و جو SQL زیر به شما امکان می دهد شناسه معامله را با بالاترین مقدار پیدا کنید: "شناسه ، حداکثر (مقدار) را از معاملات انتخاب کنید".

همانطور که مشاهده می کنید ، ما نیازی به اجرای نحوه محاسبه حداکثر مقدار (به عنوان مثال ، استفاده از حلقه ها و یک متغیر برای ردیابی بالاترین مقدار) نیست. ما فقط آنچه را که انتظار داریم بیان می کنیم. این ایده اساسی به این معنی است که شما باید کمتر در مورد چگونگی اجرای صریح چنین سؤالاتی نگران باشید - برای شما انجام می شود. چرا نمی توانیم کاری مشابه با مجموعه ها انجام دهیم؟چند بار خود را با استفاده از حلقه ها بارها و بارها مجدداً این عملیات را مجدداً اجرا می کنید؟

دوم ، چگونه می توانیم مجموعه های واقعاً بزرگ را به طور کارآمد پردازش کنیم؟در حالت ایده آل ، برای سرعت بخشیدن به پردازش ، می خواهید از معماری های چندگانه استفاده کنید. با این حال ، نوشتن کد موازی سخت و مستعد خطا است.

جاوا SE 8 به نجات! طراحان API Java در حال به روزرسانی API با انتزاع جدیدی به نام جریان هستند که به شما امکان می دهد داده ها را به روشی اعلام کننده پردازش کنید. علاوه بر این ، جریان ها می توانند بدون نیاز به نوشتن یک خط از کد چند رشته ای ، از معماری های چند هسته ای استفاده کنند. خوب به نظر می رسد ، اینطور نیست؟این همان چیزی است که این سری از مقالات کشف خواهد کرد.

در اینجا یک ایده ذهن آور وجود دارد: این دو عمل می توانند عناصر "برای همیشه" تولید کنند.

قبل از اینکه به تفصیل بپردازیم که چه کاری می توانید با جریان ها انجام دهید ، اجازه دهید به یک مثال نگاهی بیندازیم تا شما از سبک برنامه نویسی جدید با Java SE 8 Streams حس کنید. بیایید بگوییم که ما باید تمام معاملات مواد غذایی نوع را پیدا کنیم و لیستی از شناسه های معامله را که در کاهش ترتیب ارزش معامله مرتب شده اند ، بازگردانیم. در Java SE 7 ، ما این کار را همانطور که در لیست 1 نشان داده شده است انجام می دهیم. در Java SE 8 ، ما آن را همانطور که در لیست 2 نشان داده شده است انجام می دهیم.

لیست مواد غذایی لیست = ArrayList جدید<>() ؛برای (معامله T: معاملات)>Collections. Sort (مواد غذایی GroceryTransactions ، مقایسه جدید ()>) ؛لیست TransactionIds = ArrayList جدید<>() ؛برای (معامله T: مواد غذایی)

لیست 1

List transactionsIds = transactions.stream() .filter(t >t. gettype () == Transaction. Grocery) 

لیست 2

شکل 1 کد جاوا SE 8 را نشان می دهد. ابتدا با استفاده از روش جریان () موجود در لیست ، جریان را از لیست معاملات (داده ها) بدست می آوریم. در مرحله بعد ، چندین عمل (فیلتر ، مرتب شده ، نقشه ، جمع آوری) با هم زنجیر می شوند تا خط لوله ای تشکیل شوند که می تواند به عنوان تشکیل پرس و جو در داده ها دیده شود.

streams-f1

شکل 1

بنابراین در مورد موازی سازی کد چطور؟در Java SE 8 آسان است: فقط جریان () را با جریان موازی () جایگزین کنید ، همانطور که در لیست 3 نشان داده شده است ، و API جریان ها از طریق داخلی پرس و جو شما را برای استفاده از هسته های متعدد در رایانه خود تجزیه می کنند.

List transactionsIds = transactions.parallelStream() .filter(t >t. gettype () == Transaction. Grocery) 

لیست 3

Don’t worry if this code is slightly overwhelming. We will explore how it works in the next sections. However, notice the use of lambda expressions (for example, t>T. getCategor () == Transaction. Grocery) و منابع متد (به عنوان مثال ، معامله :: getId) ، که تا الان باید با آن آشنا باشید.(برای مسواک زدن به عبارات لامبدا ، به مقالات قبلی مجله جاوا و سایر منابع ذکر شده در پایان این مقاله مراجعه کنید.)

در حال حاضر ، شما می توانید یک جریان را به عنوان انتزاعی برای بیان عملیات کارآمد و شبیه SQL در مجموعه داده ها مشاهده کنید. علاوه بر این ، این عملیات می تواند به طور خلاصه با عبارات لامبدا پارامتر شود.

در پایان این مجموعه مقالات در مورد Java SE 8 جریان ، شما قادر خواهید بود از API Streams برای نوشتن کد مشابه لیست 3 برای بیان نمایش داده های قدرتمند استفاده کنید.

شروع با جریان

بیایید با کمی تئوری شروع کنیم. تعریف یک جریان چیست؟یک تعریف کوتاه "دنباله ای از عناصر از منبعی است که از عملیات کل پشتیبانی می کند."بیایید آن را تجزیه کنیم:

  • دنباله عناصر: یک جریان یک رابط به مجموعه ای از مقادیر از یک نوع عنصر خاص ارائه می دهد. با این حال ، جریان ها در واقع عناصر را ذخیره نمی کنند. آنها بر اساس تقاضا محاسبه می شوند.
  • منبع: جریان ها از یک منبع ارائه دهنده داده مانند مجموعه ها ، آرایه ها یا منابع I/O مصرف می کنند.
  • عملیات کل: جریان پشتیبانی از عملیات SQL مانند و عملیات مشترک از زبانهای برنامه نویسی عملکردی ، مانند فیلتر ، نقشه ، کاهش ، یافتن ، مطابقت ، مرتب سازی و غیره.

علاوه بر این ، عملیات جریان دارای دو ویژگی اساسی است که آنها را با عملیات مجموعه بسیار متفاوت می کند:

  • لوله کشی: بسیاری از عملیات جریان خود یک جریان را برمی گردانند. این اجازه می دهد تا عملیات زنجیر شود تا یک خط لوله بزرگتر تشکیل شود. این امر بهینه سازی های خاصی مانند تنبلی و اتصال کوتاه را امکان پذیر می کند که بعداً بررسی می کنیم.
  • تکرار داخلی: بر خلاف مجموعه ها ، که به صراحت تکرار می شوند (تکرار خارجی) ، عملیات جریان تکرار پشت صحنه را برای شما انجام می دهد.

بیایید مثال کد قبلی خود را برای توضیح این ایده ها بررسی کنیم. شکل 2 لیست 2 را با جزئیات بیشتر نشان می دهد.

streams-f2

شکل 2

ما ابتدا با فراخوانی روش جریان () جریان از لیست معاملات را دریافت می کنیم. DataSource لیست معاملات است و دنباله ای از عناصر را به جریان ارائه می دهد. در مرحله بعد ، ما یک سری عملیات کل را روی جریان اعمال می کنیم: فیلتر (برای فیلتر کردن عناصر با توجه به یک محمول) ، مرتب شده (برای مرتب کردن عناصر داده شده به یک مقایسه کننده) و نقشه (برای استخراج اطلاعات). تمام این عملیات به جز جمع آوری بازگشت یک جریان ، به طوری که می توان آنها را زنجیر کرد تا خط لوله ایجاد شود ، که می تواند به عنوان یک پرس و جو در منبع مشاهده شود.

تا زمانی که جمع آوری شود ، هیچ کاری انجام نمی شود. عملیات جمع آوری پردازش خط لوله را برای بازگشت نتیجه آغاز می کند (چیزی که جریان نیست ؛ در اینجا ، یک لیست). در حال حاضر نگران جمع آوری نباشید. ما در مقاله آینده آن را به تفصیل بررسی خواهیم کرد. در حال حاضر ، می توانید جمع آوری را به عنوان عملیاتی مشاهده کنید که به عنوان یک استدلال برای جمع آوری عناصر یک جریان به نتیجه خلاصه می رسد. در اینجا ، Tolist () دستور العمل تبدیل یک جریان را به یک لیست توصیف می کند.

قبل از اینکه روشهای مختلف موجود در یک جریان را کشف کنیم ، خوب است که مکث کرده و در مورد تفاوت مفهومی بین یک جریان و یک مجموعه تأمل کنیم.

جریان در مقابل مجموعه ها

هم مفهوم موجود در جاوا از مجموعه ها و هم مفهوم جدید جریانها رابط هایی را برای دنباله ای از عناصر فراهم می کند. بنابراین تفاوت چیست؟به طور خلاصه ، مجموعه ها در مورد داده ها هستند و جریان ها مربوط به محاسبات است.

فیلمی را که در DVD ذخیره شده است در نظر بگیرید. این یک مجموعه (شاید از بایت یا شاید فریم باشد - ما در اینجا اهمیتی نمی دهیم) زیرا حاوی کل ساختار داده است. اکنون هنگام پخش از طریق اینترنت ، تماشای همان فیلم را در نظر بگیرید. اکنون این جریان (از بایت یا فریم) است. پخش کننده ویدیوی پخش کننده باید قبل از جایی که کاربر در حال تماشای آن است ، فقط چند فریم بارگیری کرده باشد ، بنابراین می توانید قبل از اینکه بیشتر مقادیر موجود در جریان محاسبه شده باشد ، از ابتدای جریان مقادیر خود را نمایش دهید (در نظر بگیرید که پخش زنده را در نظر بگیرید. بازی فوتبال).

از نظر درشت ترین ، تفاوت بین مجموعه ها و جریان ها مربوط به محاسبه همه چیز است. یک مجموعه یک ساختار داده در حافظه است ، که تمام مقادیری را که ساختار داده در حال حاضر در اختیار دارد ، نگه می دارد-هر عنصر در مجموعه باید قبل از اضافه شدن به مجموعه محاسبه شود. در مقابل ، یک جریان یک ساختار داده ثابت مفهومی است که در آن عناصر بر اساس تقاضا محاسبه می شوند.

استفاده از رابط مجموعه نیاز به تکرار توسط کاربر دارد (به عنوان مثال ، با استفاده از حلقه پیشرفته به نام foreach). به این تکرار خارجی گفته می شود.

در مقابل ، کتابخانه جریان از تکرار داخلی استفاده می کند - این تکرار را برای شما انجام می دهد و از ذخیره ارزش جریان حاصل در جایی مراقبت می کند. شما فقط یک عملکرد را ارائه می دهید که می گوید چه کاری باید انجام شود. کد موجود در لیست 4 (تکرار خارجی با یک مجموعه) و لیست 5 (تکرار داخلی با یک جریان) این تفاوت را نشان می دهد.

لیست TransactionIds = ArrayList جدید<>() ؛برای (معامله T: معاملات)

لیست 4

لیست معاملات = transactions. stream () . map (معامله :: getId) . collect (tolist ()) ؛ 

لیست 5

در لیست 4 ، ما صریحاً لیست معاملات را به صورت متوالی تکرار می کنیم تا هر شناسه معامله را استخراج کرده و آن را به یک باتری اضافه کنیم. در مقابل ، هنگام استفاده از جریان ، هیچ تکرار صریح وجود ندارد. کد در لیست 5 یک پرس و جو ایجاد می کند ، جایی که عملیات نقشه برای استخراج شناسه های معامله پارامتر می شود و عملکرد جمع آوری جریان حاصل را به یک لیست تبدیل می کند.

اکنون باید ایده خوبی داشته باشید که یک جریان چیست و چه کاری می توانید با آن انجام دهید. حال بیایید به عملیات مختلف پشتیبانی شده توسط جریان ها نگاه کنیم تا بتوانید نمایش داده های پردازش داده خود را بیان کنید.

عملیات جریان: بهره برداری از جریان ها برای پردازش داده ها

رابط جریان در java. util . stream. stream بسیاری از عملیات را تعریف می کند ، که می تواند در دو دسته گروه بندی شود. در مثال نشان داده شده در شکل 1 ، می توانید عملیات زیر را مشاهده کنید:

  • فیلتر ، مرتب سازی شده و نقشه ، که می تواند به هم وصل شود تا یک خط لوله ایجاد شود
  • جمع آوری ، که خط لوله را بست و نتیجه ای را برگرداند

عملیات جریان که می توانند به هم وصل شوند ، عملیات میانی نامیده می شوند. آنها می توانند به هم وصل شوند زیرا نوع بازگشت آنها یک جریان است. عملیاتی که خط لوله جریان را می بندند ، عملیات ترمینال نامیده می شوند. آنها نتیجه ای از خط لوله مانند لیست ، عدد صحیح یا حتی باطل (هر نوع غیر جریان) حاصل می کنند.

شاید تعجب کنید که چرا تمایز مهم است. خوب ، عملیات میانی تا زمانی که یک عملیات ترمینال در خط لوله جریان فراخوانی نشود ، هیچ پردازشی انجام نمی دهند. آنها تنبل هستند."این امر به این دلیل است که معمولاً عملیات میانی می تواند "ادغام" شود و با عمل ترمینال به یک پاس واحد پردازش شود.

List numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8); List twoEvenSquares = numbers.stream() .filter(n >  

لیست 6

به عنوان مثال ، کد را در لیست 6 در نظر بگیرید ، که دو شماره مربع حتی از لیست مشخصی از اعداد را محاسبه می کند. ممکن است تعجب کنید که موارد زیر را چاپ می کند:

فیلتر 1 فیلتر 2 نقشه برداری 2 فیلتر 3 فیلتر 4 نقشه برداری 4 

این امر به این دلیل است که حد (2) از اتصال کوتاه استفاده می کند. ما باید فقط بخشی از جریان را پردازش کنیم ، نه همه آن ، برای بازگشت نتیجه. این شبیه به ارزیابی یک بیان بزرگ بولی است که با عملگر و اپراتور زنجیر شده است: به محض اینکه یک عبارت کاذب برگردد ، می توانیم نتیجه بگیریم که کل بیان بدون ارزیابی همه آن نادرست است. در اینجا ، محدودیت عملکرد جریان اندازه 2 را برمی گرداند.

علاوه بر این ، فیلتر عملیات و نقشه در همان پاس ادغام شده اند.

به طور خلاصه آنچه را که تاکنون آموخته ایم ، کار با جریان ها ، به طور کلی ، شامل سه چیز است:

  • منبع داده (مانند مجموعه ای) که در آن می توان یک پرس و جو را انجام داد
  • زنجیره ای از عملیات میانی ، که یک خط لوله جریان را تشکیل می دهند
  • یک عملیات ترمینال ، که خط لوله جریان را اجرا می کند و نتیجه می گیرد

API جریان ها از طریق داخلی پرس و جو شما را تجزیه می کنند تا از چندین هسته در رایانه شما استفاده کنند.

بیایید اکنون برخی از عملیات موجود در جریان ها را گشت و گذار کنیم. برای مثال بیشتر به Java. Util . Stream. Stream Interface برای لیست کامل و همچنین به منابع موجود در این مقاله مراجعه کنید.

فیلترچندین عمل وجود دارد که می تواند برای فیلتر کردن عناصر از یک جریان استفاده شود:

  • فیلتر (محمول): یک محمول (java. util. function. predicate) را به عنوان یک آرگومان می گیرد و جریانی را شامل می شود که شامل تمام عناصر مطابق با محمول داده شده است
  • مجزا: جریان را با عناصر منحصر به فرد برمی گرداند (با توجه به اجرای برابر برای یک عنصر جریان)
  • محدودیت (n): جریانی را که بیشتر از اندازه n مشخص نیست ، برمی گرداند
  • پرش (n): جریان را با اولین تعداد n عناصر دور ریخته شده برمی گرداند

پیدا کردن و تطبیقیک الگوی پردازش داده مشترک در حال تعیین اینکه آیا برخی از عناصر با یک خاصیت خاص مطابقت دارند یا خیر. برای کمک به شما در انجام این کار می توانید از عملیات Anymatch ، Allmatch و Nonematch استفاده کنید. همه آنها به عنوان یک استدلال یک محمول را می گیرند و یک بولی را به عنوان نتیجه باز می گردانند (بنابراین ، آنها عملیات ترمینال هستند). به عنوان مثال ، شما می توانید از AllMatch استفاده کنید تا بررسی کنید که تمام عناصر موجود در یک جریان معاملات دارای مقدار بالاتر از 100 هستند ، همانطور که در لیست 7 نشان داده شده است.

boolean expensive = transactions.stream() .allMatch(t > t.getValue()>100) ؛ 

لیست 7

علاوه بر این ، رابط جریان عملیات FindFirst را فراهم می کند و برای بازیابی عناصر دلخواه از یک جریان پیدا می کند. از آنها می توان در رابطه با سایر عملیات جریان مانند فیلتر استفاده کرد. هر دو FindFirst و Findany همانطور که در لیست 8 نشان داده شده است ، یک شیء اختیاری را برمی گردانند.

Optional = transactions.stream() .filter(t >t. gettype () == transaction. grocery) . Findany () ؛ 

لیست 8

کلاس اختیاری (java. util . optional) یک کلاس کانتینر برای نشان دادن وجود یا عدم وجود یک مقدار است. در لیست 8 ، این امکان وجود دارد که Findany هیچ معامله ای از نوع مواد غذایی را پیدا نکند. کلاس اختیاری شامل چندین روش برای آزمایش وجود یک عنصر است. به عنوان مثال ، اگر معامله موجود باشد ، می توانیم با استفاده از روش IFPResent ، عملیاتی را روی شیء اختیاری اعمال کنیم ، همانطور که در لیست 9 نشان داده شده است (جایی که ما فقط معامله را چاپ می کنیم).

 transactions.stream() .filter(t >t. gettype () == transaction. grocery) . findany () . ifpresent (system. out :: println) ؛ 

لیست 9

نقشه برداری. جریان ها از نقشه متد پشتیبانی می کنند ، که یک تابع (java. util. function. function) را به عنوان استدلال برای طرح عناصر یک جریان به شکل دیگری می گیرد. این تابع برای هر عنصر اعمال می شود ، "نقشه برداری" آن را به یک عنصر جدید.

به عنوان مثال ، ممکن است بخواهید از آن برای استخراج اطلاعات از هر عنصر یک جریان استفاده کنید. در مثال در لیست 10 ، لیستی از طول هر کلمه را از یک لیست برمی گردانیم. کاهشتا کنون ، عملیات ترمینال که ما دیده ایم ، یک بولی (allmatch و غیره) ، باطل (foreach) یا یک شیء اختیاری (Findany و غیره) را برمی گرداند. ما همچنین از Collect برای ترکیب همه عناصر موجود در یک جریان در یک لیست استفاده کرده ایم.

لیست کلمات = arrays. aslist ("اوراکل" ، "جاوا" ، "مجله") ؛لیست WordL طول = کلمات. srem () . map (رشته :: طول) . COLLECT (TOLIST ()) ؛ 

لیست 10

با این حال ، شما همچنین می توانید تمام عناصر را در یک جریان ترکیب کنید تا نمایش داده های فرآیند پیچیده تر مانند "معامله با بالاترین شناسه چیست؟"یا "مبلغ تمام مقادیر معاملات را محاسبه کنید."این کار با استفاده از عملکرد کاهش در جریان ها امکان پذیر است ، که به طور مکرر یک عمل (به عنوان مثال ، اضافه کردن دو عدد) را بر روی هر عنصر اعمال می کند تا نتیجه حاصل شود. این اغلب به عنوان یک عملیات برابر در برنامه نویسی کاربردی خوانده می شود زیرا می توانید این عمل را به عنوان "تاشو" مکرراً یک کاغذ بلند (جریان شما) مشاهده کنید تا اینکه یک مربع کوچک را تشکیل دهد ، که نتیجه عملیات برابر است.

این کمک می کند تا ابتدا به این موضوع نگاه کنیم که چگونه می توانیم مبلغ لیست را با استفاده از یک حلقه محاسبه کنیم:

int sum = 0 ؛برای (int x: اعداد)

هر عنصر از لیست اعداد با استفاده از اپراتور اضافی برای تولید نتیجه به طور تکراری ترکیب می شود. ما در اصل لیست اعداد را به یک شماره "کاهش می دهیم". در این کد دو پارامتر وجود دارد: مقدار اولیه متغیر جمع ، در این مورد 0 و عملکرد برای ترکیب همه عناصر لیست ، در این مورد +.

با استفاده از روش کاهش در جریان ، می توانیم تمام عناصر یک جریان را همانطور که در لیست 11 نشان داده شده است خلاصه کنیم. روش کاهش دو آرگومان طول می کشد:

int sum = numbers.stream().reduce(0, (a, b) >A + B) ؛

لیست 11

  • یک مقدار اولیه ، در اینجا 0
  • یک باینری برای ترکیب دو عنصر و تولید یک مقدار جدید

روش کاهش اساساً الگوی کاربرد مکرر را انتزاع می کند. سایر نمایش داده شدگان مانند "محاسبه محصول" یا "محاسبه حداکثر" (به لیست 12 مراجعه کنید) به موارد استفاده ویژه روش کاهش تبدیل می شوند.

int product = numbers.stream().reduce(1, (a, b) >a * b) ؛int product = number. stream (). کاهش (1 ، عدد صحیح :: حداکثر) ؛ 

لیست 12

جریانهای عددی

شما به تازگی دیده اید که می توانید از روش کاهش برای محاسبه مجموع جریان اعداد صحیح استفاده کنید. با این حال ، هزینه ای وجود دارد: ما بسیاری از عملیات بوکس را انجام می دهیم تا به طور مکرر اشیاء عدد صحیح را به هم اضافه کنیم. آیا اگر بتوانیم با یک روش جمع ، همانطور که در لیست 13 نشان داده شده است ، بخواهیم در مورد هدف کد خود صریح تر باشیم ، بهتر نخواهد بود؟

بیانیه int = transactions. stream () . map (معامله :: getValue) . sum () ؛// خطا از آنجا که جریان هیچ روش جمع ندارد 

لیست 13

Java SE 8 سه رابط جریان تخصصی اولیه را برای مقابله با این مسئله معرفی می کند - Intstream ، Doublestream و Longstream - به ترتیب عناصر یک جریان را به صورت int ، دو و طولانی تخصص می دهند.

متداول ترین روش هایی که برای تبدیل یک جریان به یک نسخه تخصصی استفاده خواهید کرد عبارتند از Matoint ، MaptoDouble و Maptolong. این روش ها دقیقاً مانند نقشه متد که قبلاً دیدیم کار می کنند ، اما آنها به جای یک جریان ، یک جریان تخصصی را برمی گردانند. به عنوان مثال ، ما می توانیم کد را در لیست 13 همانطور که در لیست 14 نشان داده شده است ، بهبود بخشیم. همچنین می توانید با استفاده از عملیات جعبه ای از یک جریان ابتدایی به جریانی از اشیاء تبدیل کنید.

intsmentum = transactions. stream () . mapoint (معامله :: getValue) . sum () ؛// آثار! 

لیست 14

سرانجام ، یکی دیگر از شکل های مفید جریان های عددی دامنه های عددی است. به عنوان مثال ، شما ممکن است بخواهید تمام اعداد را بین 1 تا 100 ایجاد کنید. Java SE 8 دو روش استاتیک موجود در IntStream ، Doublestream و Longstream را معرفی می کند تا به تولید چنین محدوده هایی کمک کند: دامنه و Rangeclosed.

هر دو روش مقدار شروع دامنه را به عنوان پارامتر اول و مقدار نهایی دامنه به عنوان پارامتر دوم می گیرند. با این حال ، دامنه منحصر به فرد است ، در حالی که Rangeclosed فراگیر است. لیست 15 نمونه ای است که از Rangeclosed برای بازگشت جریان از همه اعداد عجیب و غریب بین 10 تا 30 استفاده می کند.

IntStream oddNumbers = IntStream.rangeClosed(10, 30) .filter(n >n ٪ 2 == 1) ؛ 

لیست 15

جریانهای ساختمانی

روش های مختلفی برای ساخت جریان وجود دارد. شما دیده اید که چگونه می توانید از یک مجموعه جریانی دریافت کنید. علاوه بر این ، ما با جریان اعداد بازی کردیم. همچنین می توانید جریانی از مقادیر ، آرایه یا یک پرونده ایجاد کنید. علاوه بر این ، شما حتی می توانید جریانی از یک عملکرد برای تولید جریان های نامحدود ایجاد کنید!

ایجاد یک جریان از مقادیر یا از یک آرایه ساده است: فقط از روشهای استاتیک استفاده کنید. برای مقادیر و آرایه ها. Stream برای یک آرایه ، همانطور که در لیست 16 نشان داده شده است.

اعداد جریان از FromValues = stream. of (1 ، 2 ، 3 ، 4) ؛int [] اعداد = ؛intstream numberfromarray = arrays. stream (اعداد) ؛ 

لیست 16

برخلاف مجموعه ها ، که به صراحت تکرار می شوند (تکرار خارجی) ، عملیات جریان تکرار پشت صحنه را برای شما انجام می دهد.

همچنین می توانید با استفاده از روش Static Files. lines ، یک پرونده را در یک جریان از خطوط تبدیل کنید. به عنوان مثال ، در لیست 17 تعداد خطوط را در یک پرونده حساب می کنیم.

longoflines = files. lines (paths. get ("yourfile. txt") ، charset. defaultcharset ()). count () ؛ 

لیست 17

جریان های بی نهایت. سرانجام ، قبل از نتیجه گیری این مقاله اول در مورد جریان ، یک ایده ذهن آور وجود دارد. در حال حاضر باید درک کنید که عناصر یک جریان به صورت تقاضا تولید می شوند. دو روش استاتیک وجود دارد. جریان. با این حال ، از آنجا که عناصر در صورت تقاضا محاسبه می شوند ، این دو عمل می توانند عناصر "برای همیشه" تولید کنند. این همان چیزی است که ما آن را یک جریان نامتناهی می نامیم: جریانی که اندازه ثابت ندارد ، همانطور که یک جریان هنگام ایجاد آن از یک مجموعه ثابت انجام می دهیم.

بیشتر بدانید

  • جاوا 8 لامبدا در عمل
  • مخزن GitHub با نمونه های کد Java SE 8
  • "جاوا 8: لامبدا ، قسمت 1" توسط تد نیوارد

لیست 18 نمونه ای است که از unterate برای ایجاد جریانی از همه اعداد که چند برابر است استفاده می کند.

Stream numbers = Stream.iterate(0, n >n + 10) ؛

لیست 18

ما می توانیم با استفاده از عملیات محدود ، یک جریان نامتناهی را به یک جریان با اندازه ثابت تبدیل کنیم. به عنوان مثال ، ما می توانیم اندازه جریان را به 5 محدود کنیم ، همانطور که در لیست 19 نشان داده شده است.

اعداد. limit (5) . foreach (system. out :: println) ؛// 0 ، 10 ، 20 ، 30 ، 40

لیست 19

نتیجه

Java SE 8 API جریان را معرفی می کند ، که به شما امکان می دهد نمایش داده های پردازش داده های پیشرفته را بیان کنید. در این مقاله ، شما دیده اید که یک جریان از بسیاری از عملیات مانند فیلتر ، نقشه ، کاهش و تکرار پشتیبانی می کند که می تواند برای نوشتن نمایش داده های پردازش داده های مختصر و بیانگر ترکیب شود. این روش جدید برای نوشتن بسیار متفاوت از نحوه پردازش مجموعه ها قبل از Java SE 8 است. با این حال ، این مزایای بسیاری دارد. ابتدا ، API جریان از تکنیک های مختلفی مانند تنبلی و اتصال کوتاه برای بهینه سازی نمایش داده های پردازش داده شما استفاده می کند. دوم ، جریان ها می توانند به طور خودکار به صورت موازی برای استفاده از معماری های چند هسته ای موازی شوند. در مقاله بعدی در این سری ، ما عملیات پیشرفته تری مانند Flatmap و Collect را بررسی خواهیم کرد. گوش به زنگ باشید.

Raoul-Gabriel Urma

رائول گابریل اروما در حال حاضر دکترای علوم کامپیوتر را در دانشگاه کمبریج تکمیل می کند ، جایی که وی در زبان های برنامه نویسی تحقیق می کند. علاوه بر این ، او نویسنده Java 8 در Action: Lambdas ، جریان و برنامه نویسی به سبک عملکردی است (منینگ ، 2014).

استراتژی ترید...
ما را در سایت استراتژی ترید دنبال می کنید

برچسب : نویسنده : مرجان شیرمحمدی بازدید : 30 تاريخ : جمعه 10 شهريور 1402 ساعت: 15:29