JavaRush /Kurslar /All lectures for UZ purposes /Lambdalar paydo bo'lish tarixi

Lambdalar paydo bo'lish tarixi

All lectures for UZ purposes
Daraja, Dars
Mavjud

1. Interfeyslar

Lambdalar nima ekanligini tushunish uchun, avval interfeyslar nima ekanligini tushunish kerak. Shuning uchun asosiy fikrlarni eslaymiz.

Interfeys — bu sinfning bir turi. Juda qisqartirilgan, agar shunday deyish mumkin bo'lsa. Interfeysda, sinfdan farqli o'laroq, o'zining o'zgaruvchilari bo'lishi mumkin emas (statikdan tashqari). Shuningdek, Interfeys turidagi obyektlarni yaratish mumkin emas:

  • Sinf o'zgaruvchilarini e'lon qilish mumkin emas
  • Obyektlarni yaratish mumkin emas

Misol:

interface Runnable
{
   void run();
}
Standart interfeys misoli

Interfeysdan foydalanish

Interfeyslar nima uchun kerak? Interfeyslar faqat meros olish bilan birga qo'llaniladi. Xuddi shu interfeysni turli sinflar meros qilib olishlari mumkin, yoki aytiladi, bu sinflar interfeysni realizatsiya qiladilar.

Agar sinf interfeysni realizatsiya qilsa, u interfeys ichida e'lon qilingan, lekin amalga oshirilmagan metodlarni o'z ichida amalga oshirishi lozim. Misol:

interface Runnable
{
   void run();
}

class Timer implements Runnable
{
   void run()
   {
      System.out.println(LocalTime.now());
   }
}

class Calendar implements Runnable
{
   void run()
   {
      var date = LocalDate.now();
      System.out.println("Bugun " + date.getDayOfWeek());
   }
}

Timer sinfi Runnable interfeysini amalga oshiradi (implements), shuning uchun u interfeysda Runnable mavjud barcha metodlarni o'z ichida e'lon qilishi va ularni amalga oshirishi kerak: metod tanasida kod yozish. Bu Calendar clasiga ham tegishli.

Endi Runnable turidagi o'zgaruvchilarga, Runnable interfeysini amalga oshiradigan sinf obyektlariga havolalarni saqlash mumkin.

Misol:

Kod Izoh
Timer timer = new Timer();
timer.run();

Runnable r1 = new Timer();
r1.run();

Runnable r2 = new Calendar();
r2.run();

Metod run() Timer sinfidan chaqiriladi


Metod run() Timer sinfidan chaqiriladi


Metod run() Calendar sinfidan chaqiriladi

Obyektga havolani istalgan turdagi o'zgaruvchiga tayinlashingiz mumkin, agar bu tur - obyektning ota sinflaridan biri bo'lsa. Timer va Calendar sinflari uchun bunday turlardan ikkita : Object va Runnable.

Agar siz Object turidagi o'zgaruvchiga obyekt havolasini tayinlasangiz, unga faqat Object sinfida e'lon qilingan metodlarni chaqira olasiz. Agar Runnable turidagi o'zgaruvchiga obyekt havolasini tayinlasangiz, Runnable turidagi metodlarni chaqira olasiz.

Misol 2:

ArrayList<Runnable> list = new ArrayList<Runnable>();
list.add (new Timer());
list.add (new Calendar());

for (Runnable element: list)
    element.run();

Bunday kod ishlaydi, chunki Timer va Calendar obyektlarida a'lo darajada ishlaydigan run metodlari mavjud. Shuning uchun ularni chaqirishda hech qanday muammo yo'q. Agar biz faqat ikkala sinfga run() metodini qo'shsak, ularni bunday oddiy usulda chaqira olmas edik.

Runnable interfeysi asosan run metodini joylashtirish uchun foydalaniladi.



2. Saralash

Endi esa biroz amaliy narsalarga o'tamiz. Masalan, qatorlarni tartiblashni ko'rib chiqaylik.

Java-da kolleksiyani alfavit tartibida tartiblang, juda ajoyib metod bor — Collections.sort(kollektsiya);

Bu statik metod o'ziga berilgan kolleksiyani tartiblaydi va tartiblash jarayonida uning elementlarini juft-juft solishtiradi, elementlarni almashtirish kerakmi yoki yo'qmi tushunish uchun.

Kolleksiya elementlarini solishtirish compareTo() metodi yordamida amalga oshiriladi, bu metod barcha standart sinflarda mavjud: Integer, String, ...

Integer sinfining compareTo() metodi ikkita son qiymatini solishtiradi, String sinfining compareTo() metodi esa qatorlarni alfavit tartibida ko'rib chiqadi.

Natijada, sonlar kolleksiyasi ularning ko'payish tartibida, qatorlar kolleksiyasi esa alfavit tartibida tartiblanadi.

Muqobil saralash

Agar biz qatorlarni alfavit bo'yicha emas, balki ularning uzunligi bo'yicha saralashni xohlasak-chi? Va sonlarni kamayish tartibida saralashni xohlaymiz. Bu vaziyatda qanday bo'lish kerak?

Buning uchun Collections sinfida yana bir metod sort() mavjud, ammo ikki parametr bilan:

Collections.sort(kollektsiya, komparator);

Bu yerda komparator — bu ob'ektlarni solishtirishni biladigan maxsus ob'ekt kollektsiyasida tartiblash jarayonida. Komparator inglizcha Comparator so'zidan kelib chiqqan (solishtiruvchi), va Comparator — Compare so'zidan — solishtirish.

Afsuski, bu maxsus ob'ekt nima?

Comparator interfeysi

Hammasi juda oddiy. sort() metodining ikkinchi parametri turi - Comparator<T>

Bu yerda T – bu parametr turi, kollektsiya elementlarining turi kabi, va Comparator — bu yagona int compare(T obj1, T obj2); metodiga ega interfeys.

Boshqacha aytganda, komparator ob'ekti — bu Comparator interfeysini amalga oshiruvchi har qanday sinf ob'ekti. Comparator interfeysi juda oddiy ko'rinadi:

public interface Comparator<T>
{
   public int compare(T obj1, T obj2);
}
Comparator interfeys kodi

compare() metodi ikkita parametrni solishtiradi, ularni o'tkazadi.

Agar metod manfiy sonni qaytarsa, obj1 < obj2. Agar metod musbat sonni qaytarsa, obj1 > obj2. Agar metod 0 ni qaytarsa, u holda obj1 == obj2 deb hisoblanadi.

Qatorlarni uzunligi bo'yicha solishtiradigan komparator ob'ekti bunday ko'rinadi:

public class StringLengthComparator implements Comparator<String>
{
   public int compare (String obj1, String obj2)
   {
      return obj1.length() - obj2.length();
   }
}
StringLengthComparator sinf kodi

Qatorlar uzunligini solishtirish uchun faqat bitta uzunlikni boshqasidan chiqarish kifoya.

StringLengthComparator sinfidan to'liq foydalanishni ko'rish uchun boshqa kodni ko'rib chiqamiz:

public class Solution
{
   public static void main(String[] args)
   {
      ArrayList<String> list = new ArrayList<String>();
      Collections.addAll(list, "Salom", "qanday", "ishlar?");
      Collections.sort(list, new StringLengthComparator());
   }
}

class StringLengthComparator implements Comparator<String>
{
   public int compare (String obj1, String obj2)
   {
      return obj1.length() - obj2.length();
   }
}
Qatorlarni uzunligi bo'yicha saralash


3. Sintaktik shakar

Bu kodni qisqaroq yozish mumkinmi? Aslida, bu yerda faqat bitta qator mavjud, bu muhim axborotni olib turadi — obj1.length() - obj2.length();.

Lekin kod metoddan tashqarida mavjud bo'la olmaydi, shuning uchun compare metod qo'shish kerak bo'ldi, va metod uchun yangi sinf qo'shish kerak bo'ldi – StringLengthComparator. Va o'zgaruvchi turlarni ko'rsatish kerak... Xullas, hammasi to'g'ri.

Lekin, bu kodni qisqaroq yozish usullari mavjud. Siz uchun bir oz sintaktik shakar tayyorlangan. Ushbu dastur har doim ikki chelak ko'rinishida!

Anonim ichki sinf

Siz Comparator kodini to'g'ridan-to'g'ri main() metodida yozishingiz mumkin, va kompilator qolgan barcha ishlarni o'zi bajaradi. Misol:

public class Solution
{
    public static void main(String[] args)
    {
        ArrayList<String> list = new ArrayList<String>();
        Collections.addAll(list, "Salom", "qanday", "ishlar?");

        Comparator<String> comparator = new Comparator<String>()
        {
            public int compare (String obj1, String obj2)
            {
                return obj1.length() - obj2.length();
            }
        };

        Collections.sort(list, comparator);
    }
}
Qatorlarni uzunligi bo'yicha saralash

Siz Comparator interfeysining merosxo'r ob'yektini sinfni yaratmasdan yaratishingiz mumkin! Kompilator uni avtomatik ravishda yaratadi va unga vaqtinchalik nom beradi. Solishtiring:

Comparator<String> comparator = new Comparator<String>()
{
    public int compare (String obj1, String obj2)
    {
        return obj1.length() - obj2.length();
    }
};
Anonim ichki sinf
Comparator<String> comparator = new StringLengthComparator();

class StringLengthComparator implements Comparator<String>
{
    public int compare (String obj1, String obj2)
    {
        return obj1.length() - obj2.length();
    }
}
StringLengthComparator sinfi

Ikki holatdagi kodning bir xil bloklari bir xil rang bilan ranglangan. Farqlar aslida juda kichik.

Kompilator birinchi kod blokini kodda uchratganda, u uchun ikkinchi kod blokini yaratiladi va sinfga qandaydir vaqtinchalik nom beradi.


4. Java da Lambdalar

Faraz qilaylik, siz kodda anonim ichki sinfni ishlatishga qaror qildingiz. Bunday holda sizda quyidagi kod bo'ladi:

Comparator<String> comparator = new Comparator<String>()
{     public int compare (String obj1, String obj2)
    {
        return obj1.length() - obj2.length();
    }
};
Anonim ichki sinf

Bu yerda o'zgaruvchi e'loni va anonim sinfni yaratish - barchasi birga. Ammo bu kodni qisqaroq yozish mumkin. Masalan, quyidagicha:

Comparator<String> comparator = (String obj1, String obj2) ->
{
    return obj1.length() - obj2.length();
};

Nuqtavirgul kerak, chunki sizda bu yerda nafaqat yashirin sinf e'loni, balki o'zgaruvchini yaratish ham mavjud.

Bunday yozuv lambda ifodasi deb ataladi.

Agar kompilator sizning kodingizda bunday ifodani uchratsa, u oddiygina to'liq versiyasini (anonim ichki sinf bilan) yaratadi.

Diqqat qiling: lambda ifodasini yozganda, biz faqat Comparator<String> sinf nomini emas, balki int compare() metod nomini ham o'tkazib yubordik.

Kompilyator metodni aniqlashda muammoga duch kelmaydi, chunki lambda ifodasi faqat bitta metodga ega interfeyslar uchun yozilishi mumkin. Biroq, bu qoidani aylanib o'tish usuli mavjud, ammo bu haqda siz OOPni faolroq o'rganishni boshlaganingizda bilib olasiz (bu default-metodlar haqida gaplashamiz).

Kodning to'liq versiyasiga yana bir bor qaraymiz, faqat uning bir qismini kul rangda bo'yaymiz, uni lambda ifodasi yozishda o'tkazib yuborish mumkin:

Comparator<String> comparator = new Comparator<String>()
{
    public int compare (String obj1, String obj2)
    {
      return obj1.length() - obj2.length();
    }
};
Anonim ichki sinf

Ko'rinib turibdi, biz hech qanday muhim narsani o'tkazib yuborganimiz yo'q. Aslida, agar Comparator interfeysida faqat bitta compare() metodi mavjud bo'lsa, qolgan koddan kompilator kulrang kodni qayta tiklashi mumkin.

Sorting

Kodi endi quyidagicha yozilishi mumkin:

Comparator<String> comparator = (String obj1, String obj2) ->
{
   return obj1.length() - obj2.length();
};
Collections.sort(list, comparator);

Yoki hatto bunday:

Collections.sort(list, (String obj1, String obj2) ->
   {
      return obj1.length() - obj2.length();
   }
);

Biz faqat comparator o'zgaruvchini o'rniga darhol tayinladik comparator o'zgaruvchiga qaytarilgan qiymatni.

Typing

Lekin bu hali hammasi emas. Bu misolning kodini yanada qisqaroq yozish mumkin. Birinchidan, kompilator o'zi obj1 va obj2 o'zgaruvchilari String turi ekanligini aniqlashi mumkin. Ikkinchidan, figurali qavslar va return operatori kerak emas, agar metodning kodida faqat bitta buyruq bo'lsa.

Qisqatilgan variant quyidagicha bo'ladi:

Comparator<String> comparator = (obj1, obj2) ->
   obj1.length() - obj2.length();

Collections.sort(list, comparator);

Agar comparator o'zgaruvchisi o'rniga darhol uning qiymatini tayinlasak, quyidagi variant chiqadi:

Collections.sort(list, (obj1, obj2) ->  obj1.length() - obj2.length() );

Xo'sh, qanday: faqat bitta kod satri, hech qanday ortiqcha ma'lumot yo'q - faqat o'zgaruvchilar va kod. Qisqartirish mumkin bo'lgan joy qolmadimi? Yoki hali ham bor?



5. Bu qanday ishlaydi

Aslida, kodni yanada qisqaroq yozish mumkin. Ammo bu haqida bir ozdan keyin.

Lambda ifodasi birgina metodli interfeys turidan foydalangan joyga yozilishi mumkin.

Misol uchun, bu kodda Collections.sort(list, (obj1, obj2) -> obj1.length() - obj2.length()); lambda ifodasi yozilishi mumkin, chunki sort() metodining imzosi quyidagicha:

sort(Collection<T> colls, Comparator<T> comp)

Biz birinchi parametr sifatida sort metodiga ArrayList<String> kolleksiyasini o'tkazganimizda, kompilator ikkinchi parametr turini Comparator<String> sifatida belgilashi mumkin. Buning asosida, bu interfeys int compare(String obj1, String obj2) yagona metodiga ega ekanligini aniqladi. Qolgan ish texnika masalasi.

Izohlar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION