تعبيرات Java Lambda هي ميزة جديدة تم تقديمها بواسطة Java 8. يمكن القول أنها سكر بناء الجملة للبرمجة الوظيفية المحاكاة. أنها تشبه الإغلاق في JavaScript ، لكنها مختلفة إلى حد ما. والغرض الرئيسي هو توفير بناء جملة وظيفية لتبسيط ترميزنا.
جملة Lambda الأساسية
الهيكل الأساسي لاممدا هو (الحجج) -> الجسم ، وهناك عدة مواقف:
يحتاج الجسم إلى تضمين عبارات مع {} ، ويمكن حذف {} عندما يكون هناك بيان واحد فقط.
أساليب الكتابة الشائعة هي كما يلي:
(أ) -> أ * أ
(int a ، int b) -> a + b
(A ، B) -> {return a - b ؛}
() -> system.out.println (thread.currentThread (). getId ())
الوظيفية الوظيفية
مفهوم
تعتمد تعبيرات Java Lambda على واجهات وظيفية. ما هي الواجهة الوظيفية؟ ببساطة ، إنها واجهة مع طريقة واحدة فقط (وظيفة). الغرض من هذا النوع من الواجهة هو لعملية واحدة ، والتي تعادل وظيفة واحدة. الواجهات الشائعة مثل Runnable والمقارنة هي واجهات وظيفية ، ويتم شرحها مع functionalInterface.
إعطاء مثال
من السهل فهم استخدام مؤشر الترابط كمثال. واجهة Runnable هي واجهة شائعة الاستخدام عندما نرسل برمجة سلسلة ، والتي تتضمن طريقة void run () ، وهي منطق تشغيل مؤشر الترابط. وفقًا للبناء السابق ، عادة ما نستخدم فئة مجهول Runnable لإنشاء مؤشرات ترابط جديدة ، على النحو التالي:
مؤشر ترابط جديد (جديد RunNable () {Override public void run () {system.out.println (thread.currentThread (). getId ()) ؛}}). start () ؛إذا كتبت كثيرًا ، أليس كذلك مملًا؟ تصبح قواعد الكتابة القائمة على Lambda موجزة وواضحة ، على النحو التالي:
موضوع جديد (() -> system.out.println (thread.currentThRead (). getId ())). start () ؛
انتبه إلى معلمات الموضوع. يتم تنفيذ التنفيذ المجهول لـ RunNable في جملة واحدة ، ويتم كتابته كما يلي لفهم أفضل.
RunNable r = () -> system.out.println (thread.currentThRead (). getId ()) ؛
موضوع جديد (ص) .start () ؛
بطبيعة الحال ، فإن الغرض من Lambda ليس فقط الكتابة بإيجاز ، ولكن لتلخيص الغرض العالي المستوى بعد فهمه.
دعونا نلقي نظرة على مثال آخر على المقارنة. وفقًا لطريقة الكتابة التقليدية ، على النحو التالي:
integer [] a = {1 ، 8 ، 3 ، 9 ، 2 ، 0 ، 5} ؛ arrays.sort (a ، new Neyment <integer> () {Override public int compare (integer o1 ، integer o2) {return o1 - o2 ؛}}) ؛تعبيرات Lambda مكتوبة على النحو التالي:
integer [] a = {1 ، 8 ، 3 ، 9 ، 2 ، 0 ، 5} ؛
arrays.sort (a ، (O1 ، O2) -> O1 - O2) ؛
واجهات وظيفية في JDK
لكي تستخدم مكتبة الفئة الحالية تعبيرات Lambda مباشرة ، كانت هناك بعض الواجهات في Java 8 التي تم تمييزها كواجهات وظيفية:
تمت إضافة حزمة جديدة java.util.function إلى Java 8 ، مما يجلب الواجهة الوظيفية الشائعة الاستخدام:
بالإضافة إلى ذلك ، تتم إضافة المزيد من الوظائف المحددة إلى معالجة الأنواع الأساسية ، بما في ذلك: Booleansupplier ، doublebinaryOperator ، doubleConsumer ، doublefunction <r> ، doublepredicate ، doublesupplier ، doubletopintfunction ، doubletoLongfunction ، doubletolongfunction ، doubleOperatoratoratoratorator ، intbrinication ، int ، intsupplier ، inttodoublefunction ، inttolongfunction ، intunaryOperator ، longbinaryoperator ، longconsumer ، longfunction <r> ، longpredicate ، longsupplier ، longtodoublefunction ، tootbiftfunction ، longunarypoarator ، todoubleBifunction <t ، u> ، tointfunction <T> ، tolongbifunction <t ، u> ، tolongfunction <T>. إلى جانب الواجهات الوظيفية أعلاه ، يمكنك رؤية دور الواجهة في لمحة من خلال اسم فئة هذه الواجهات الوظيفية الأساسية.
إنشاء واجهة وظيفية
في بعض الأحيان نحتاج إلى تنفيذ واجهة وظيفية بأنفسنا ، والطريقة بسيطة للغاية. أولاً ، يجب عليك التأكد من أن هذه الواجهة يمكن أن تحتوي فقط على تشغيل وظيفة واحدة ، ثم توضيح functionalInterface على نوع الواجهة.
اكتب الاشتقاق
اشتقاق النوع هو أساس تعبيرات Lambda ، وعملية اشتقاق النوع هي عملية تجميع تعبيرات Lambda. الرمز التالي مثال:
وظيفة <string ، integer> strtoint = str -> integer.parseint (str) ؛
أثناء التجميع ، فإن عملية اشتقاق النوع التي أفهمها هي كما يلي:
النوع الهدف هنا هو المفتاح ، ويتم الحصول على توقيع الطريقة من خلال نوع الهدف ثم قارنه بتعبير Lambda.
طريقة المرجع
أساس مرجع الطريقة (مرجع الطريقة) هو أيضًا واجهة وظيفية ، والتي يمكن تنفيذها مباشرة كواجهة وظيفية ، لها نفس وظيفة تعبيرات Lambda وتعتمد أيضًا على اشتقاق النوع. يمكن اعتبار مراجع الطريقة على أنها تبسيط تعبيرات Lambda التي تستدعي طريقة واحدة فقط.
بناء الجملة المشار إليه بواسطة الطريقة هو: Type :: MethodName أو InstancEname :: MethodName ، و methodname المقابل للمُنشئ جديد.
على سبيل المثال ، تم استخدام الأمثلة أعلاه:
وظيفة <string ، integer> strtoint = str -> integer.parseint (str) ؛
مرجع الطريقة المقابلة
وظيفة <string ، integer> strtoint = integer :: parseint ؛
وفقًا لنوع الطريقة ، يتم تقسيم مراجع الطريقة بشكل أساسي إلى الأنواع التالية: مرجع طريقة المنشئ ، مرجع الطريقة الثابتة ، مرجع طريقة المثيل على المثيل ، مرجع طريقة المثيل على النوع ، إلخ.
مرجع طريقة المنشئ
بناء الجملة هو: النوع :: جديد. على سبيل المثال ، الوظيفة التالية هي تحويل سلسلة إلى صفيف
طريقة الكتابة المرجعية
وظيفة <string ، integer> strtoint = integer :: new ؛
كتابة لامدا
دالة <string ، integer> strtoint = str -> integer new (str) ؛
الكتابة التقليدية
الدالة <string ، integer> strtoint = new function <string ، integer> () {Override public integer تطبيق (String str) {return new integer (str) ؛ }} ؛
مرجع منشئ الصفيف
بناء الجملة هو: اكتب [] :: جديد. على سبيل المثال ، الوظيفة التالية هي إنشاء مجموعة سلسلة من الطول المحدد
طريقة الكتابة المرجعية
دالة <integer ، string []> fixedarray = string [] :: new ؛
طريقة الكتابة المرجعية
الدالة <integer ، string []> fixedarray = length -> سلسلة جديدة [طول] ؛
الكتابة التقليدية
الدالة <integer ، string []> ثابت = وظيفة جديدة <integer ، string []> () {Override public string [] تطبيق (طول الصدفة) {return new string [length] ؛ }} ؛مرجع طريقة ثابتة
بناء الجملة هو: النوع :: جديد. نظرًا لأن الوظيفة التالية تستخدم أيضًا لتحويل السلاسل إلى صفائف
طريقة الكتابة المرجعية
وظيفة <string ، integer> strtoint = integer :: parseint ؛
كتابة لامدا
وظيفة <string ، integer> strtoint = str -> integer.parseint (str) ؛
الكتابة التقليدية
الدالة <string ، integer> strtoint = new function <string ، integer> () {Override public integer تطبيق (String str) {return integer.parseint (str) ؛ }} ؛مرجع طريقة المثيل على مثيل
بناء الجملة هو: instancename :: methodname. على سبيل المثال ، يتم استخدام وظيفة الحكم التالية لتحديد ما إذا كان الاسم المحدد موجودًا في القائمة
قائمة <Tring> names = arrays.aslist (سلسلة جديدة [] {"Zhang San" ، "Li Si" ، "Wang Wu"}) ؛
Predicate <string> checkNameExists = names :: يحتوي ؛
System.out.println (CheckNameExists.test ("Zhang San")) ؛
System.out.println (CheckNameExists.test ("Zhang Si")) ؛
مرجع طريقة المثيل على النوع
بناء الجملة هو: type :: methodname. يشير مرجع وقت التشغيل إلى كائن في السياق ، مثل الوظيفة أدناه لإرجاع طول السلسلة
الدالة <string ، integer> calcstrlength = string :: length ؛ system.out.println (calcstrlength.apply ("Zhang San") ؛ قائمة <string> names = arrays.aslist (سلسلة جديدة [] {"Zhangsan" ، "lisi" ، "wangwu"}) ؛
على سبيل المثال ، حددت الوظيفة التالية فاصلًا لتقسيم السلسلة إلى صفيف
bifunction <string ، string ، string []> split = string :: split ؛
string [] names = split.apply ("Zhangsan ، Lisi ، Wangwu" ، "،") ؛
System.out.println (Arrays.ToString (Names)) ؛
دفق الكائنات
مفهوم
ما هو الدفق؟ يختلف الدفق هنا عن InputStream و OutputStream في IO. يقع Stream في الحزمة java.util.stream ويتم إضافته حديثًا إلى Java 8. Stream هو مجرد مجموعة من العناصر التي تدعم عمليات التجميع المتوازية التسلسلية ، والتي يمكن فهمها كنسخة محسّنة من مجموعة أو مؤلف. ما هي عملية التجميع؟ لإعطاء مثال بسيط ، تشمل تلك الشائعة الوسط ، الحد الأقصى ، الحد الأدنى ، المجموع ، الفرز ، التصفية ، إلخ.
عدة ميزات للتيار:
معالجة واحدة. بعد اكتمال معالجة واحدة ، يتم إغلاق الدفق الحالي.
دعم الطرق الشائعة للحصول على تدفقات في العمليات الموازية
احصل من المجموعة
collection.stream () ؛
collection.parallelstream () ؛
مصنع ثابت
المصفوفات.
Stream.of (T ...)
intstream.range ()
هنا سنقدم فقط مقدمة موجزة للتيار ، وسيكون هناك تطبيقات محددة أدناه. إذا كنت ترغب في التحدث عن العلاقة بين تعبيرات التيار وتعبيرات Lambda ، فلا توجد في الواقع علاقة وثيقة بشكل خاص. إنها تعبيرات Lambda تسهل بشكل كبير استخدام التيار. بدون تعبيرات Lambda ، سيتم إنشاء عدد كبير من الفصول المجهولة أثناء استخدام التيار ، وهو أمر محرج للغاية.
إعطاء مثال
تعتمد العروض التوضيحية التالية على كائن الموظف وكائن القائمة المكون من كائن الموظف.
موظف الفئة العامة {اسم السلسلة الخاصة ؛ جنسية سلسلة خاصة عصر INT الخاص ؛ الموظف العام (اسم السلسلة ، سلسلة الجنس ، int) {super () ؛ this.name = name ؛ this.Sex = الجنس ؛ this.age = العمر ؛ } السلسلة العامة getName () {return name ؛ } سلسلة عامة getSex () {return sex ؛ } public int getage () {return Age ؛ } Override Public String ToString () {StringBuilder Builder = new StringBuilder () ؛ builder.append ("الموظف {name ="). إلحاق (name) .append ("، sex ="). إلحاق (الجنس). إرجاع builder.toString () ؛ }} قائمة <evelope> الموظفين = ArrayList New ArrayList <> () ؛ الموظفين. ADD (موظف جديد ("Zhang San" ، "Male" ، 25)) ؛ الموظفين. ADD (موظف جديد ("Li Si" ، "أنثى" ، 24)) ؛ الموظفين. المعدل (موظف جديد ("وانغ وو" ، "أنثى" ، 23)) ؛ موظفين (موظف جديد ("السبت" ، "ذكر" ، 22)) ؛ موظفون (موظف جديد ("صن تشى" ، "أنثى" ، 21)) ؛ موظفين (موظف جديد ("ليو با" ، "ذكر" ، 20)) ؛طباعة جميع الموظفين
يوفر المجموعة طريقة foreach بالنسبة لنا لتشغيل كائنات فردية واحدة تلو الأخرى.
الموظفين. foreach (e -> system.out.println (e)) ؛
أو
الموظفين.
فرز حسب العمر
collections.sort (الموظفين ، (E1 ، E2) -> e1.getage () - e2.getage ()) ؛
الموظفين. foreach (e -> system.out.println (e)) ؛
أو
الموظفين.
اطبع أقدم موظفة
أقصى/دقيقة يعيد العنصر الأكبر/الدقيقة في ظل ظروف الفرز المحددة
الموظف maxagefemaleemployee = الموظفين.
طباعة الموظفين الذكور الذين تزيد أعمارهم عن 20 عامًا
تصفية عناصر تفي بالمعايير
الموظفين.
.filter (e -> e.getage ()> 20 && "ذكر" .equals (
. foreach (e -> system.out.println (e)) ؛
اطبع أقدم الموظفين الذكور
طريقة الحد تعترض عناصر محدودة
الموظفين.
اطبع أسماء جميع الموظفين الذكور ، والاستخدام ، منفصلين
خريطة لتشكيل دفق جديد بعد تنفيذ الوظيفة المحددة.
string maleMployeSnames = amploy.stream () .map (e ->
المعلومات الإحصائية
INTSUMMARYSTATINSICS ، الزوجي undercamaryStatistics ، LongsummaryStatistics يحتوي على بيانات موجزة في الدفق.
intsummaryStatistics stat = staff.stream () .Maptoint (effecte :: getage) .SummaryStatistics () ؛ system.out.println ("العدد الإجمالي للموظفين:" + stat.getCount ()) ؛ system.out.println ("الحد الأقصى العمر:" Stat.getMin ()) ؛ system.out.println ("متوسط العمر:" + stat.getAverage ()) ؛لخص
تعبيرات Lambda يمكن أن تقلل بالفعل الكثير من التعليمات البرمجية وتحسن الإنتاجية. بالطبع ، هناك عيوب ، أي أن التعبيرات المعقدة ستكون قابلة للقراءة بشكل سيء ، أو قد تكون لأنها ليست معتادة للغاية عليها. إذا اعتدت على ذلك ، أعتقد أنك ستعجبك. كل شيء له جانبان ، يعتمد ذلك على كيفية موازنة إيجابيات وسلبيات ، وخاصة في الفريق.
ما سبق هو المعلومات التي تقوم بفرز Java8 Javalambda. سنستمر في إضافة المعلومات ذات الصلة في المستقبل. شكرا لدعمكم لهذا الموقع!