پیاده‌سازی حلقه‌های تودرتو با استفاده از لامبدا در جاوا ۸

۲۴ دی ۱۳۹۵

جاوا یک زبان برنامه‌نویسیِ شیءگرا است که برای نخستین بار توسط جیمز گاسلینگ در شرکت سان مایکروسیستمز ایجاد گردید. یکی از قابلیت‌های بنیادین جاوا این است که مدیریت حافظه را بطور خودکار انجام می‌دهد. ضریب اطمینان عملکرد برنامه‌های نوشته‌شده به این زبان نسبت به زبانهای نسل اول C بالا است و وابسته به سیستم‌عامل خاصی نیست. فرض کنید یک List یا Set از یک parentObject داریم که آن نیز یک لیست یا List یا Set از یک childObject دارد. می‌خواهیم روی یکی از peopertyهای خاص childObject یک مقایسه انجام دهیم.



راه‌حل اولیه برای این کار استفاده از دو حلقه for تودرتو به صورت زیر است:


for (ParentObject parentObject : parentObjects)
    for (ChildObject childObject : parentObject.getChildObjects())
        if (childObject.getProperty().equals(anObject))
            return true; // one parentObject matches...

یکی از راه‌حل‌های پیشنهادی برای انجام این کار، استفاده از Lambda Expressions و stream در جاوا ۸ است. برای این منظور می‌توانیم از قطعه کد زیر استفاده کنیم:


parentObjects.stream().anyMatch(p -> p.getChildObjects().stream().anyMatch(c -> c.getProperty().equals(anObject)));

در کد بالا روی parentObject یک Stream ایجاد شده و سپس یک Stream دیگر روی childObject ایجاد کردیم و با متد anyMatch  درصورت پیداکردن اولین تطابق خروجیtrueو درغیر اینصورت false خواهد بود.

۴ نظر:

۱۳۹۵/۱۰/۲۶،‏ ۱۶:۰۹ مهدی تاجیک گفت...

به نظرم متن آموزش می تونه کمی بلند تر باشه و مفید تر باشه واقعاً آموزش اتفاق بیافتد. مثلا در اینجا توضیح دهید که steam چیست و کارش چیت، map چیست و نحوه کار را چند مثال بزنید. با تشکر

۱۳۹۵/۱۰/۲۷،‏ ۱:۱۴
مرتضی اسدی گفت...

ضمن تشکر از شما، باید بگویم توضیح دادن Stream کمی سخت است، Stream یک interface است که بیشتر در lambda expressionها کاربرد دارد. Stream با collection (مثل List یا Set) تفاوت‌هایی دارد از جمله اینکه:

Stream یک data structure نیست که عناصر را ذخیره کند.
عملیات روی Stream خروجی تولید می‌کند؛ اما منبع (source) اصلی را تغییر نمی‌دهد.
بسیاری از عملیات روی Strem مانند (filtering، mapping، و duplicate) قابلیت این را دارند که به صورت lazy پیاده‌سازی شوند.
یک Collection اندازه محدود دارد ولی stream نه.
در طی حیات یک Stream، عناصر آن فقط یکبار visit‌ می‌شوند.

اگر علاقمندید بیشتر بخوانید؛ نگاهی به مستندات رسمی بیندازید.

در خصوص map نیز باید یدانید یکی از عملیاتی که روی Streamها تعریف می‌شود، map است و یک قسمت از مدل برنامه‌نویسی Map-Reduce است که (به طور خلاصه) داده‌ها را به قسمت‌های مجزا شکسته (map می‌کند) و پس محاسبات بر روی قسمت‌های مجزا و گرفتن خروجی، با تجمیع خروجی‌ها (reduce) نتیجه کل را حساب می‌کند.

۱۳۹۵/۱۰/۲۷،‏ ۱۶:۱۲
احمد گفت...

سلام.
در این مثال از تابع flatMap هم میتوان استفاده کرد.
public boolean matches(Collection parentObjects, Object anObject) {
return parentObjects.stream().flatMap(p -> p.getChildren().stream()).anyMatch(c -> c.getProperty().equals(anObject));
}

۱۳۹۵/۱۰/۲۷،‏ ۲۱:۲۷
مرتضی اسدی گفت...

با سلام و درود، flatMap هم یکی از عملیات روی Stream است و نظر شما کاملا درست است.