JavaRush /جاوا بلاگ /Random-SD /Lambda اظهار مثالن سان

Lambda اظهار مثالن سان

گروپ ۾ شايع ٿيل
جاوا شروعاتي طور تي مڪمل طور تي اعتراض تي مبني ٻولي آهي. ابتدائي قسمن جي استثنا سان، جاوا ۾ هر شيء هڪ اعتراض آهي. جيتوڻيڪ صفون شيون آهن. هر طبقي جا مثال شيون آهن. الڳ الڳ فعل جي وضاحت ڪرڻ جو ڪو به امڪان نه آهي (ڪلاس کان ٻاهر - تقريباً ترجمو. ). ۽ ڪو به طريقو ناهي ته هڪ طريقو هڪ دليل جي طور تي پاس ڪرڻ يا ڪنهن ٻئي طريقي جي نتيجي ۾ هڪ طريقي جي جسم کي واپس ڪرڻ. ائين ئي آهي. پر اهو جاوا 8 کان اڳ هو. Lambda اظهار مثالن سان - 1سٺي پراڻي سوئنگ جي ڏينهن کان وٺي، اهو ضروري هو ته گمنام طبقن کي لکڻو پوندو جڏهن ڪجهه ڪارڪردگي کي ڪجهه طريقي سان منتقل ڪرڻ ضروري هو. مثال طور، اھو اھو آھي جيڪو ھڪڙو ايونٽ ھينڊلر شامل ڪرڻ جھڙو آھي:
someObject.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {

                //Event listener implementation goes here...

            }
        });
هتي اسان ڪجهه ڪوڊ شامل ڪرڻ چاهيون ٿا مائوس ايونٽ لسٽر ۾. اسان هڪ گمنام طبقي جي وضاحت ڪئي MouseAdapter۽ فوري طور تي ان مان هڪ اعتراض ٺاهيو. هن طريقي سان، اسان ۾ اضافي ڪارڪردگي کي منظور ڪيو آهي addMouseListener. مختصر ۾، جاوا ۾ هڪ سادي طريقو (ڪارڪردگي) کي دليلن ذريعي منتقل ڪرڻ آسان ناهي. ھن حد بندي جاوا 8 ڊولپرز کي ھڪڙي خصوصيت شامل ڪرڻ تي مجبور ڪيو جھڙوڪ Lambda ايڪسپريسز کي ٻولي جي وضاحت ۾.

ڇو جاوا کي Lambda اظهار جي ضرورت آهي؟

شروعات کان وٺي، جاوا ٻولي گهڻو ترقي نه ڪئي آهي، سواءِ تشريحات، جنريڪس وغيره جي. سڀ کان پهرين، جاوا هميشه اعتراض تي مبني رهي آهي. فنڪشنل ٻولين جهڙوڪ جاوا اسڪرپٽ سان ڪم ڪرڻ کان پوء، ڪو به سمجهي سگهي ٿو ته ڪيئن جاوا سختي سان اعتراض تي مبني ۽ مضبوط ٽائپ ٿيل آهي. جاوا ۾ ڪم جي ضرورت ناهي. پاڻ طرفان، اهي جاوا جي دنيا ۾ نه ڳولي سگهجن ٿا. فنڪشنل پروگرامنگ ٻولين ۾، افعال سامهون اچن ٿا. اهي پاڻ ۾ موجود آهن. توھان انھن کي متغير ڏانھن تفويض ڪري سگھو ٿا ۽ انھن کي دليلن ذريعي ٻين ڪمن ڏانھن منتقل ڪري سگھو ٿا. JavaScript فنڪشنل پروگرامنگ ٻولين جي بهترين مثالن مان هڪ آهي. توهان انٽرنيٽ تي سٺا مضمون ڳولي سگهو ٿا جيڪي جاوا اسڪرپٽ جي فائدن کي هڪ فنڪشنل ٻولي طور بيان ڪن ٿا. فنڪشنل ٻولين ۾ طاقتور اوزار آهن جهڙوڪ بندش، جيڪي روايتي طريقن جي ايپليڪيشنن جي لکڻين تي ڪيترائي فائدا مهيا ڪن ٿا. هڪ بندش هڪ فنڪشن آهي جنهن سان ڳنڍيل ماحول آهي - هڪ ٽيبل جيڪو ذخيرو ڪري ٿو حوالن جي سڀني غير مقامي متغيرن جا. جاوا ۾، بندش Lambda اظهار ذريعي ٺاهي سگھجن ٿيون. يقينن، بندش ۽ ليمبڊا اظهار جي وچ ۾ فرق آهن، ۽ ننڍا نه آهن، پر ليمبڊا اظهار بندش لاء سٺو متبادل آهن. هن جي طنزيه ۽ مزاحيه بلاگ ۾، اسٽيو يگ بيان ڪري ٿو ته ڪيئن جاوا جي دنيا سختي سان اسمن سان ڳنڍيل آهي (ادارا، شيون - تقريبا. ترجمو ). جيڪڏهن توهان هن جو بلاگ نه پڙهيو آهي، آئون ان جي سفارش ڪريان ٿو. هن هڪ مضحکہ خیز ۽ دلچسپ انداز ۾ بيان ڪيو آهي ته صحيح سبب ڇو ته Lambda ايڪسپريس جاوا ۾ شامل ڪيا ويا. Lambda ايڪسپريس جاوا ۾ ڪارڪردگي آڻيندو آهي جيڪا گهڻي عرصي کان غائب آهي. Lambda ايڪسپريس صرف شين وانگر ٻوليء ۾ ڪارڪردگي آڻيندو آهي. جڏهن ته اهو 100٪ صحيح ناهي، توهان ڏسي سگهو ٿا ته Lambda ايڪسپريس، جڏهن ته بند نه ٿي رهيو آهي، ساڳيون صلاحيتون مهيا ڪن ٿيون. هڪ فنڪشنل ٻولي ۾، لامبڊا اظهار افعال آهن؛ پر جاوا ۾، lambda ايڪسپريشن کي شين جي نمائندگي ڪري ٿو، ۽ لازمي طور تي هڪ مخصوص اعتراض جي قسم سان لاڳاپيل هوندو جنهن کي فنڪشنل انٽرفيس سڏيو ويندو آهي. اڳتي هلي اسان ڏسنداسين ته اهو ڇا آهي. ماريو فوسڪو جو مضمون ”ڇو اسان کي جاوا ۾ ليمبڊا ايڪسپريشن جي ضرورت آهي“ تفصيل سان بيان ڪري ٿو ته سڀني جديد ٻولين کي بند ڪرڻ جي صلاحيتن جي ضرورت ڇو آهي.

Lambda ايڪسپريس جو تعارف

Lambda ايڪسپريس گمنام افعال آهن (شايد جاوا لاءِ 100٪ صحيح تعريف نه هجي، پر اهو ڪجهه وضاحت آڻيندو آهي). سادي لفظ ۾، هي هڪ طريقو آهي بغير اعلان جي، يعني. بغير رسائي جي تبديلين، موٽڻ واري قيمت ۽ نالو. مختصر ۾، اهي توهان کي هڪ طريقو لکڻ جي اجازت ڏين ٿا ۽ ان کي فوري طور تي استعمال ڪريو. اهو خاص طور تي ڪارائتو آهي صورت ۾ هڪ-وقت طريقو ڪال، ڇاڪاڻ ته اهو وقت گھٽائي ٿو جيڪو ڪلاس ٺاهڻ کان سواءِ هڪ طريقو بيان ڪرڻ ۽ لکڻ ۾ وٺندو آهي. جاوا ۾ Lambda ايڪسپريس عام طور تي ھيٺ ڏنل نحو آھي (аргументы) -> (тело). مثال طور:
(арг1, арг2...) -> { тело }

(тип1 арг1, тип2 арг2...) -> { тело }
هيٺ ڏنل حقيقي Lambda اظهار جا ڪجهه مثال آهن:
(int a, int b) -> {  return a + b; }

() -> System.out.println("Hello World");

(String s) -> { System.out.println(s); }

() -> 42

() -> { return 3.1415 };

Lambda ايڪسپريس جي جوڙجڪ

اچو ته لامبڊا اظهار جي ساخت جو مطالعو ڪريون:
  • Lambda ايڪسپريسز ۾ 0 يا وڌيڪ ان پٽ پيٽرول هوندا.
  • پيٽرولر جو قسم واضح طور تي بيان ڪري سگھجي ٿو يا حوالن مان حاصل ڪري سگھجي ٿو. مثال طور ( int a) هن طرح لکي سگهجي ٿو ( a)
  • پيرا ميٽرز قوس ۾ بند ٿيل آهن ۽ ڪاما سان الڳ ٿيل آهن. مثال طور ( a, b) يا ( int a, int b) يا ( String a, int b, float c)
  • جيڪڏهن ڪو به پيٽرولر نه آهي، ته توهان کي خالي قوس استعمال ڪرڻ جي ضرورت آهي. مثال طور() -> 42
  • جڏهن صرف هڪ پيٽرولر آهي، جيڪڏهن قسم واضح طور تي بيان نه ڪيو ويو آهي، قوس کي ختم ڪري سگهجي ٿو. مثال:a -> return a*a
  • هڪ Lambda اظهار جي جسم ۾ 0 يا وڌيڪ اظهار شامل ٿي سگهن ٿا.
  • جيڪڏهن جسم هڪ واحد بيان تي مشتمل آهي، اهو ٿي سگهي ٿو ڳوڙها ڪڙيون ۾ بند نه ڪيو وڃي، ۽ واپسي جي قيمت لفظ جي بغير بيان ڪري سگهجي ٿي return.
  • ٻي صورت ۾، گھمڻ وارا ڪنگڻ گھربل آھن (ڪوڊ جو بلاڪ) ۽ واپسي جي قيمت آخر ۾ مخصوص لفظ استعمال ڪندي بيان ڪيو وڃي return(ٻي صورت ۾ واپسي جو قسم ٿيندو void).

هڪ فنڪشنل انٽرفيس ڇا آهي

جاوا ۾، مارڪر انٽرفيس انٽرفيس آهن بغير بيان ڪيل طريقن يا فيلڊن جي. ٻين لفظن ۾، ٽوڪن انٽرفيس خالي انٽرفيس آھن. اهڙي طرح، فنڪشنل انٽرفيس انٽرفيس آهن جن تي صرف هڪ خلاصو طريقو بيان ڪيو ويو آهي. java.lang.Runnableهڪ فنڪشنل انٽرفيس جو هڪ مثال آهي. اهو صرف هڪ طريقو بيان ڪري ٿو void run(). اتي پڻ ھڪڙو انٽرفيس آھي ActionListener- پڻ فنڪشنل. اڳي، اسان کي گمنام ڪلاس استعمال ڪرڻو پوندو هو شيون ٺاهڻ لاءِ جيڪي فنڪشنل انٽرفيس کي لاڳو ڪن. Lambda اظهار سان، هر شيء آسان ٿي چڪي آهي. هر ليمبڊا اظهار واضح طور تي ڪجهه فنڪشنل انٽرفيس تي پابند ٿي سگهي ٿو. مثال طور، توهان Runnableهڪ انٽرفيس جو حوالو ٺاهي سگهو ٿا، جيئن هيٺ ڏنل مثال ۾ ڏيکاريل آهي:
Runnable r = () -> System.out.println("hello world");
اهڙي قسم جي تبديلي هميشه واضح طور تي ڪئي ويندي آهي جڏهن اسان هڪ فنڪشنل انٽرفيس جي وضاحت نه ڪندا آهيون:
new Thread(
    () -> System.out.println("hello world")
).start();
مٿين مثال ۾، مرتب ڪندڙ خود بخود lambda ايڪسپريس ٺاهي ٿو جيئن Runnableانٽرفيس کي لاڳو ڪرڻ لاءِ ڪلاس ڪنسٽرڪٽر Thread: public Thread(Runnable r) { }. هتي ڪجهه مثال آهن lambda اظهار جا ۽ لاڳاپيل فنڪشنل انٽرفيس:
Consumer<Integer> c = (int x) -> { System.out.println(x) };

BiConsumer<Integer, String> b = (Integer x, String y) -> System.out.println(x + " : " + y);

Predicate<String> p = (String s) -> { s == null };
جاوا 8 ۾ شامل ڪيل تشريح @FunctionalInterfaceجاوا ٻولي جي وضاحت جي مطابق چيڪ ڪري ٿي ته ڇا اعلان ڪيل انٽرفيس ڪم ڪري ٿو. اضافي طور تي، جاوا 8 ۾ شامل آهن ڪيترن ئي تيار ڪيل فنڪشنل انٽرفيس استعمال ڪرڻ لاءِ Lambda اظهار سان. @FunctionalInterfaceهڪ تاليف جي غلطي اڇلائي ڇڏيندو جيڪڏهن اعلان ڪيل انٽرفيس ڪم نه ڪندو آهي. هيٺ ڏنل هڪ فنڪشنل انٽرفيس کي بيان ڪرڻ جو هڪ مثال آهي:
@FunctionalInterface
public interface WorkerInterface {

    public void doSomeWork();

}
جيئن ته تعريف ڏيکاري ٿي، هڪ فنڪشنل انٽرفيس صرف هڪ تجريدي طريقو ٿي سگهي ٿو. جيڪڏهن توهان هڪ ٻيو خلاصو طريقو شامل ڪرڻ جي ڪوشش ڪندا، توهان کي تاليف جي غلطي ملندي. مثال:
@FunctionalInterface
public interface WorkerInterface {

    public void doSomeWork();

    public void doSomeMoreWork();

}
نقص
Unexpected @FunctionalInterface annotation
    @FunctionalInterface ^ WorkerInterface is not a functional interface multiple
    non-overriding abstract methods found in interface WorkerInterface 1 error
После определения функционального интерфейса, мы можем его использовать и получать все преимущества Lambda-выражений. Пример:// defining a functional interface
@FunctionalInterface
public interface WorkerInterface {

    public void doSomeWork();

}
public class WorkerInterfaceTest {

    public static void execute(WorkerInterface worker) {
        worker.doSomeWork();
    }

    public static void main(String [] args) {

      // calling the doSomeWork method via an anonymous class
      // (classic)
      execute(new WorkerInterface() {
            @Override
            public void doSomeWork() {
               System.out.println("Worker called via an anonymous class");
            }
        });

      // calling the doSomeWork method via Lambda expressions
      // (Java 8 new)
      execute( () -> System.out.println("Worker called via Lambda") );
    }

}
نتيجو:
Worker вызван через анонимный класс
Worker вызван через Lambda
هتي اسان اسان جي پنهنجي فنڪشنل انٽرفيس جي وضاحت ڪئي آهي ۽ هڪ lambda اظهار استعمال ڪيو آهي. طريقو execute()هڪ دليل طور lambda اظهار کي قبول ڪرڻ جي قابل آهي.

Lambda اظهار جا مثال

ليمبڊا جي اظهار کي سمجهڻ جو بهترين طريقو چند مثالن تي نظر رکڻ آهي: هڪ وهڪرو Threadٻن طريقن سان شروع ڪري سگهجي ٿو:
// Old way:
new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println("Hello from thread");
    }
}).start();
// New way:
new Thread(
    () -> System.out.println("Hello from thread")
).start();
جاوا 8 ۾ ايونٽ مئنيجمينٽ پڻ ٿي سگھي ٿو Lambda ايڪسپريسز ذريعي. ActionListenerUI جزو ۾ ايونٽ هينڊلر شامل ڪرڻ جا هيٺيان ٻه طريقا آهن :
// Old way:
button.addActionListener(new ActionListener() {
    @Override
    public void actionPerformed(ActionEvent e) {
        System.out.println("Button pressed. Old way!");
    }
});
// New way:
button.addActionListener( (e) -> {
        System.out.println("Button pressed. Lambda!");
});
ڏنل صف جي سڀني عناصر کي ظاهر ڪرڻ جو هڪ سادي مثال. نوٽ ڪريو ته ليمبڊا ايڪسپريس استعمال ڪرڻ لاءِ هڪ کان وڌيڪ طريقا آهن. هيٺ اسان هڪ لامبڊا ايڪسپريشن ٺاهيندا آهيون عام طريقي سان تير نحو استعمال ڪندي، ۽ اسان پڻ استعمال ڪريون ٿا ڊبل ڪولن آپريٽر (::)، جيڪو جاوا 8 ۾ هڪ باقاعده طريقي کي ليمبڊا ايڪسپريشن ۾ تبديل ڪري ٿو:
// Old way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
for(Integer n: list) {
    System.out.println(n);
}
// New way:
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);
list.forEach(n -> System.out.println(n));
// New way using double colon operator ::
list.forEach(System.out::println);
هيٺ ڏنل مثال ۾، اسان هڪ فنڪشنل انٽرفيس استعمال ڪندا آهيون Predicateهڪ ٽيسٽ ٺاهڻ ۽ شيون پرنٽ ڪرڻ لاءِ جيڪي امتحان پاس ڪن ٿا. هن طريقي سان توهان منطق کي لامبڊا اظهار ۾ وجهي سگهو ٿا ۽ ان جي بنياد تي شيون ڪري سگهو ٿا.
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Main {

    public static void main(String [] a)  {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7);

        System.out.print("Outputs all numbers: ");
        evaluate(list, (n)->true);

        System.out.print("Does not output any number: ");
        evaluate(list, (n)->false);

        System.out.print("Output even numbers: ");
        evaluate(list, (n)-> n%2 == 0 );

        System.out.print("Output odd numbers: ");
        evaluate(list, (n)-> n%2 == 1 );

        System.out.print("Output numbers greater than 5: ");
        evaluate(list, (n)-> n > 5 );

    }

    public static void evaluate(List<Integer> list, Predicate<Integer> predicate) {
        for(Integer n: list)  {
            if(predicate.test(n)) {
                System.out.print(n + " ");
            }
        }
        System.out.println();
    }

}
نتيجو:
Выводит все числа: 1 2 3 4 5 6 7
Не выводит ни одного числа:
Вывод четных чисел: 2 4 6
Вывод нечетных чисел: 1 3 5 7
Вывод чисел больше 5: 6 7
Lambda ايڪسپريسز سان ٽڪرائڻ سان، توھان لسٽ جي ھر عنصر جي چورس کي ڊسپلي ڪري سگھو ٿا. نوٽ ڪريو ته اسان طريقو استعمال ڪري رهيا آهيون stream()باقاعده فهرست کي هڪ وهڪرو ۾ تبديل ڪرڻ لاء. جاوا 8 هڪ بهترين ڪلاس مهيا ڪري ٿو Stream( java.util.stream.Stream). اهو ڪيترن ئي مفيد طريقن تي مشتمل آهي جنهن سان توهان استعمال ڪري سگهو ٿا lambda اظهار سان. اسان هڪ لامبڊا ايڪسپريشن x -> x*xکي طريقي سان منتقل ڪريون ٿا map()، جيڪو ان کي وهڪرو جي سڀني عنصرن تي لاڳو ڪري ٿو. جنهن کان پوء اسان forEachفهرست جي سڀني عناصر کي پرنٽ ڪرڻ لاء استعمال ڪندا آهيون.
// Old way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
for(Integer n : list) {
    int x = n * n;
    System.out.println(x);
}
// New way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
list.stream().map((x) -> x*x).forEach(System.out::println);
هڪ فهرست ڏني وئي، توهان کي فهرست جي سڀني عناصر جي چوڪن جو مجموعو پرنٽ ڪرڻو پوندو. Lambda ايڪسپريس توهان کي صرف ڪوڊ جي هڪ لائن لکڻ سان حاصل ڪرڻ جي اجازت ڏئي ٿو. هي مثال استعمال ڪري ٿو convolution (گهٽائي) جو طريقو reduce(). اسان map()هر عنصر کي چورس ڪرڻ لاء هڪ طريقو استعمال ڪندا آهيون، ۽ پوء هڪ طريقو استعمال ڪريو reduce()سڀني عناصر کي هڪ واحد نمبر ۾ ختم ڪرڻ لاء.
// Old way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = 0;
for(Integer n : list) {
    int x = n * n;
    sum = sum + x;
}
System.out.println(sum);
// New way:
List<Integer> list = Arrays.asList(1,2,3,4,5,6,7);
int sum = list.stream().map(x -> x*x).reduce((x,y) -> x + y).get();
System.out.println(sum);

Lambda اظهار ۽ گمنام طبقن جي وچ ۾ فرق

بنيادي فرق لفظ جي استعمال ۾ آهي this. گمنام طبقن لاءِ، '' لفظ thisگمنام طبقي جي هڪ شئي کي ظاهر ڪري ٿو، جڏهن ته لامبڊا اظهار ۾، ' this' ڪلاس جي هڪ اعتراض کي ظاهر ڪري ٿو جنهن ۾ lambda اظهار استعمال ڪيو ويو آهي. ٻيو فرق اهو آهي ته انهن کي ترتيب ڏيڻ جو طريقو آهي. جاوا لامبڊا ايڪسپريس کي گڏ ڪري ٿو ۽ انهن کي privateڪلاس جي طريقن ۾ بدلائي ٿو. هي استعمال ڪري ٿو invokedynamic instruction ، جاوا 7 ۾ متعارف ٿيل متحرڪ طريقي جي پابند لاءِ. ٽال ويس پنهنجي بلاگ ۾ بيان ڪيو ته ڪيئن جاوا ليمبڊا ايڪسپريسز کي بائيٽ ڪوڊ ۾ گڏ ڪري ٿو

نتيجو

مارڪ رين هولڊ (Oracle جي چيف آرڪيٽيڪٽ) ليمبڊا ايڪسپريسز کي پروگرامنگ ماڊل ۾ سڀ کان وڌيڪ اهم تبديلي سڏيو آهي جيڪا ڪڏهن به آئي آهي - عام کان به وڌيڪ اهم. هن کي صحيح هجڻ گهرجي، ڇاڪاڻ ته ... اهي جاوا پروگرامرز کي فنڪشنل پروگرامنگ ٻولي صلاحيتون ڏين ٿيون جن جو هرڪو انتظار ڪري رهيو آهي. جدت سان گڏ جيئن ته ورچوئل ايڪسٽينشن جا طريقا، Lambda ايڪسپريشنز توهان کي تمام اعليٰ معيار جو ڪوڊ لکڻ جي اجازت ڏين ٿا. مون کي اميد آهي ته هي آرٽيڪل توهان کي جاوا 8 جي هود هيٺ هڪ نظر ڏنو آهي. سٺي قسمت :)
تبصرا
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION