CodeGym /Blog Jawa /Acak /Panjelasan babagan ekspresi lambda ing basa Jawa. Kanthi ...
John Squirrels
tingkat
San Francisco

Panjelasan babagan ekspresi lambda ing basa Jawa. Kanthi conto lan tugas. Bagean 1

Diterbitake ing grup
Artikel iki kanggo sapa?
  • Iku kanggo wong sing mikir wis ngerti Java Core, nanging ora ngerti babagan ekspresi lambda ing basa Jawa. Utawa mungkin dheweke wis krungu babagan ekspresi lambda, nanging rincian kurang
  • Iku kanggo wong sing duwe pangerten tartamtu babagan ekspresi lambda, nanging isih wedi karo dheweke lan ora biasa nggunakake.
Panjelasan babagan ekspresi lambda ing basa Jawa.  Kanthi conto lan tugas.  Bagean 1 - 1Yen sampeyan ora cocog karo salah siji saka kategori iki, sampeyan bisa nemokake artikel iki mboseni, cacat, utawa umume ora cangkir teh. Ing kasus iki, aja ragu-ragu pindhah menyang perkara liyane utawa, yen sampeyan wis ngerti babagan topik kasebut, mangga menehi saran ing komentar babagan carane aku bisa nambah utawa nambah artikel kasebut. Materi kasebut ora ngaku nduweni nilai akademis, apamaneh kebaruan. Kosok baline: Aku bakal nyoba njlèntrèhaké bab-bab sing rumit (kanggo sawetara wong) kanthi gampang. A panjalukan kanggo nerangake Stream API inspirasi kula kanggo nulis iki. Aku mikir babagan iki lan mutusake manawa sawetara conto streamku ora bisa dingerteni tanpa ngerti ekspresi lambda. Dadi, kita bakal miwiti nganggo ekspresi lambda. Apa sampeyan kudu ngerti kanggo ngerti artikel iki?
  1. Sampeyan kudu ngerti pemrograman berorientasi objek (OOP), yaiku:

    • kelas, obyek, lan prabédan ing antarane;
    • antarmuka, carane padha beda-beda saka kelas, lan hubungan antarane antarmuka lan kelas;
    • cara, carane nelpon, cara abstrak (yaiku cara tanpa implementasine), paramèter metode, argumen metode lan cara kanggo ngliwati;
    • akses modifiers, cara statis / variabel, cara final / variabel;
    • warisan kelas lan antarmuka, sawetara warisan antarmuka.
  2. Kawruh Basa Jawa: jinis generik (generik), kumpulan (dhaptar), utas.
Inggih, ayo diterusake.

Sajarah sethitik

Ekspresi Lambda teka ing Jawa saka pemrograman fungsional, lan saka matématika. Ing Amerika Serikat ing tengah abad kaping 20, Gréja Alonzo, sing seneng banget karo matématika lan kabeh jinis abstraksi, kerja ing Universitas Princeton. Gereja Alonzo sing nemokke kalkulus lambda, sing wiwitane minangka kumpulan ide abstrak sing ora ana hubungane karo pemrograman. Matématikawan kayata Alan Turing lan John von Neumann makarya ing Universitas Princeton ing wektu sing padha. Kabeh teka bebarengan: Gréja teka munggah karo kalkulus lambda. Turing ngembangake mesin komputasi abstrak, saiki dikenal minangka "mesin Turing". Lan von Neumann ngusulake arsitèktur komputer sing dadi basis komputer modern (saiki diarani "arsitektur von Neumann"). Nalika iku, Gereja Alonzo Ide-ide kasebut ora kondhang kaya karya kanca-kancane (kajaba ing bidang matematika murni). Nanging, sethitik mengko John McCarthy (uga lulusan Universitas Princeton lan, ing wektu crita kita, karyawan Institut Teknologi Massachusetts) dadi kasengsem ing gagasan Church. Ing taun 1958, dheweke nggawe basa pemrograman fungsional pisanan, LISP, adhedhasar gagasan kasebut. Lan 58 taun sabanjure, ide-ide pemrograman fungsional bocor menyang Jawa 8. Ora nganti 70 taun kepungkur ... Jujur, iki dudu sing paling dawa kanggo ngetrapake ide matematika ing praktik. pegawe Institut Teknologi Massachusetts) dadi kasengsem ing gagasan Gréja. Ing taun 1958, dheweke nggawe basa pemrograman fungsional pisanan, LISP, adhedhasar gagasan kasebut. Lan 58 taun sabanjure, ide-ide pemrograman fungsional bocor menyang Jawa 8. Ora nganti 70 taun kepungkur ... Jujur, iki dudu sing paling dawa kanggo ngetrapake ide matematika ing praktik. pegawe Institut Teknologi Massachusetts) dadi kasengsem ing gagasan Gréja. Ing taun 1958, dheweke nggawe basa pemrograman fungsional pisanan, LISP, adhedhasar gagasan kasebut. Lan 58 taun sabanjure, ide-ide pemrograman fungsional bocor menyang Jawa 8. Ora nganti 70 taun kepungkur ... Jujur, iki dudu sing paling dawa kanggo ngetrapake ide matematika ing praktik.

Atine prakara

Ekspresi lambda minangka jinis fungsi. Sampeyan bisa dianggep minangka cara Jawa biasa nanging kanthi kemampuan khas kanggo diterusake menyang metode liya minangka argumen. Bener. Wis dadi bisa kanggo pass ora mung nomer, strings, lan kucing kanggo cara, nanging uga cara liyane! Kapan kita butuh iki? Iku bakal mbiyantu, contone, yen kita arep kanggo pass sawetara cara callback. Yaiku, yen kita butuh metode sing kita sebut duwe kemampuan kanggo nelpon sawetara metode liyane sing kita tindakake. Ing tembung liyane, supaya kita duwe kemampuan kanggo pass siji callback ing kahanan tartamtu lan callback beda ing liyane. Lan supaya cara kita sing nampa callbacks nelpon. Ngurutake minangka conto prasaja. Upaminipun kita nulis sawetara algoritma ngurutake pinter sing katon kaya iki:

public void mySuperSort() { 
    // We do something here 
    if(compare(obj1, obj2) > 0) 
    // And then we do something here 
}
Ing ifstatement, kita nelpon compare()cara, maringaken ing rong obyek kanggo dibandhingake, lan kita pengin ngerti kang obyek iki "luwih gedhe". Kita nganggep sing "luwih gedhe" sadurunge sing "kurang". Aku sijine "luwih gedhe" ing kuotasi, amarga kita nulis cara universal sing bakal ngerti carane ngurutake ora mung ing urutan munggah, nanging uga ing urutan mudhun (ing kasus iki, obyek "luwih gedhe" bakal bener dadi obyek "kurang" , lan kosok balene). Kanggo nyetel algoritma tartamtu kanggo urutan kita, kita butuh sawetara mekanisme kanggo ngliwati mySuperSort()metode kasebut. Kanthi cara iki, kita bakal bisa "ngontrol" metode kasebut nalika diarani. Mesthi, kita bisa nulis rong cara kapisah - mySuperSortAscend()lanmySuperSortDescend()- kanggo ngurutake ing urutan munggah lan mudhun. Utawa kita bisa ngirim sawetara argumentasi menyang metode kasebut (contone, variabel boolean; yen bener, banjur urutake ing urutan munggah, lan yen salah, banjur ing urutan mudhun). Nanging apa yen kita pengin ngurutake sing rumit kayata dhaptar array senar? Kepiye mySuperSort()cara kita ngerti carane ngurutake array senar kasebut? Miturut ukuran? Miturut dawa kumulatif kabeh tembung? Mbok miturut abjad adhedhasar senar pisanan ing array? Lan yen kita kudu ngurutake dhaptar array kanthi ukuran array ing sawetara kasus, lan kanthi dawa kumulatif kabeh tembung ing saben array ing kasus liyane? Aku ngarepake sampeyan wis krungu babagan komparator lan ing kasus iki, kita mung bakal menehi cara ngurutake obyek komparator sing nggambarake algoritma pangurutan sing dikarepake. Amarga standarsort()cara dileksanakake adhedhasar prinsip padha mySuperSort(), Aku bakal nggunakake sort()ing conto sandi.

String[] array1 = {"Dota", "GTA5", "Halo"}; 
String[] array2 = {"I", "really", "love", "Java"}; 
String[] array3 = {"if", "then", "else"}; 

List<String[]> arrays = new ArrayList<>(); 
arrays.add(array1); 
arrays.add(array2); 
arrays.add(array3); 

Comparator<;String[]> sortByLength = new Comparator<String[]>() { 
    @Override 
    public int compare(String[] o1, String[] o2) { 
        return o1.length - o2.length; 
    } 
}; 

Comparator<String[]> sortByCumulativeWordLength = new Comparator<String[]>() { 

    @Override 
    public int compare(String[] o1, String[] o2) { 
        int length1 = 0; 
        int length2 = 0; 
        for (String s : o1) { 
            length1 += s.length(); 
        } 

        for (String s : o2) { 
            length2 += s.length(); 
        } 

        return length1 - length2; 
    } 
};

arrays.sort(sortByLength);
asil:

  1. Dota GTA5 Halo
  2. if then else
  3. I really love Java
Ing kene, larik diurutake miturut jumlah tembung ing saben larik. Larik kanthi tembung sing luwih sithik dianggep "kurang". Pramila ingkang rumiyin. Larik kanthi tembung liyane dianggep "luwih gedhe" lan diselehake ing pungkasan. Yen kita ngliwati komparator sing beda karo sort()metode kasebut, kayata sortByCumulativeWordLength, mula kita bakal entuk asil sing beda:

  1. if then else
  2. Dota GTA5 Halo
  3. I really love Java
Saiki array diurutake miturut jumlah total huruf ing tembung array. Ing array pisanan, ana 10 huruf, ing kaloro - 12, lan katelu - 15. Yen kita mung duwe comparator siji, banjur kita ora kudu wara-wara variabel kapisah kanggo iku. Nanging, kita mung bisa nggawe kelas anonim ing wektu nelpon sort()metode kasebut. Kaya iki:

String[] array1 = {"Dota", "GTA5", "Halo"}; 
String[] array2 = {"I", "really", "love", "Java"}; 
String[] array3 = {"if", "then", "else"}; 

List<String[]> arrays = new ArrayList<>(); 

arrays.add(array1); 
arrays.add(array2); 
arrays.add(array3); 

arrays.sort(new Comparator<String[]>() { 
    @Override 
    public int compare(String[] o1, String[] o2) { 
        return o1.length - o2.length; 
    } 
}); 
Kita bakal entuk asil sing padha kaya ing kasus sing sepisanan. Tugas 1. Tulis maneh conto iki supaya ngurutake larik ora ing urutan munggah saka jumlah tembung ing saben larik, nanging ing urutan mudhun. Kita wis ngerti kabeh iki. Kita ngerti carane ngirim obyek menyang metode. Gumantung apa sing kita butuhake saiki, kita bisa ngirim obyek sing beda menyang metode, sing banjur bakal nggunakake metode sing ditindakake. Iki dadi pitakonan: kenapa ing jagad iki kita butuh ekspresi lambda ing kene?  Amarga ekspresi lambda minangka obyek sing nduweni persis siji metode. Kaya "obyek metode". Cara sing dikemas ing obyek. Iku mung duwe sintaks sing rada ora pati ngerti (nanging luwih akeh babagan mengko). Ayo deleng maneh kode iki:

arrays.sort(new Comparator<String[]>() { 
    @Override 
    public int compare(String[] o1, String[] o2) { 
        return o1.length - o2.length; 
    } 
});
Ing kene kita njupuk dhaptar array lan nelpon sort()cara, sing kita pass obyek komparator kanthi compare()cara siji (jenenge ora masalah kanggo kita - sawise kabeh, iku mung cara obyek iki, supaya kita ora bisa salah). Cara iki duwe rong paramèter sing bakal digarap. Yen sampeyan lagi makarya ing IntelliJ IDEA, sampeyan bisa uga ndeleng tawaran kasebut kanthi signifikan ngembun kode kaya ing ngisor iki:

arrays.sort((o1, o2) -> o1.length - o2.length);
Iki nyuda enem baris kanggo siji singkat. 6 baris ditulis maneh dadi siji cekak. Ana sing ilang, nanging aku njamin ora ana sing penting. Kode iki bakal bisa digunakake kanthi cara sing padha karo kelas anonim. Tugas 2. Njupuk guess ing rewriting solusi kanggo Tugas 1 nggunakake expression lambda (paling paling, takon IntelliJ IDEA Ngonversi kelas anonim kanggo expression lambda).

Ayo dadi pirembagan bab antarmuka

Ing asas, antarmuka mung dhaptar cara abstrak. Nalika kita nggawe kelas sing nindakake sawetara antarmuka, kelas kita kudu ngleksanakake cara sing kalebu ing antarmuka (utawa kita kudu nggawe abstrak kelas). Ana antarmuka karo akeh cara beda (contone,  List), lan ana antarmuka karo mung siji cara (contone, Comparatorutawa Runnable). Ana antarmuka sing ora duwe cara siji (sing diarani antarmuka panandha kayata Serializable). Antarmuka sing mung nduweni siji cara uga diarani antarmuka fungsional . Ing Jawa 8, malah ditandhani karo anotasi khusus:@FunctionalInterface. Antarmuka siji-cara iki sing cocog minangka jinis target kanggo ekspresi lambda. Kaya sing dakkandhakake ing ndhuwur, ekspresi lambda minangka cara sing dibungkus ing obyek. Lan nalika kita ngliwati obyek kasebut, kita ateges ngliwati metode siji iki. Pranyata kita ora peduli apa sing diarani metode kasebut. Siji-sijine perkara sing penting kanggo kita yaiku paramèter metode lan, mesthi, awak metode kasebut. Intine, ekspresi lambda minangka implementasi antarmuka fungsional. Ing ngendi wae kita ndeleng antarmuka kanthi cara siji, kelas anonim bisa ditulis maneh minangka lambda. Yen antarmuka duwe luwih utawa kurang saka siji cara, ekspresi lambda ora bisa digunakake lan kita bakal nggunakake kelas anonim utawa malah conto kelas biasa. Saiki iku wektu kanggo dig menyang lambdas dicokot. :)

Sintaksis

Sintaks umum kaya iki:

(parameters) -> {method body}
Yaiku, kurung sing ngubengi paramèter metode, "panah" (kawangun kanthi tandha hubung lan luwih saka tandha), banjur awak metode ing kurung, kaya biasane. Parameter kasebut cocog karo sing ditemtokake ing metode antarmuka. Yen jinis variabel bisa ditemtokake kanthi jelas dening kompiler (ing kasus kita, ngerti yen kita nggarap array string, amarga obyek Listdiketik nggunakake String[]), mula sampeyan ora kudu nuduhake jinise.
Yen padha ambigu, banjur nuduhake jinis. IDEA bakal menehi werna abu-abu yen ora dibutuhake.
Sampeyan bisa maca liyane ing tutorial Oracle iki lan ing papan liya. Iki diarani " target typing ". Sampeyan bisa menehi jeneng variabel apa wae sing dikarepake - sampeyan ora kudu nggunakake jeneng sing padha sing ditemtokake ing antarmuka. Yen ora ana paramèter, mung nuduhake kurung kosong. Yen mung ana siji parameter, mung nuduhake jeneng variabel tanpa tanda kurung. Saiki kita ngerti paramèter, wektune kanggo ngrembug awak ekspresi lambda. Ing njero kurung kriting, sampeyan nulis kode kaya cara biasa. Yen kode sampeyan kalebu siji baris, sampeyan bisa ngilangi kurungan kriting kabeh (padha karo pernyataan yen lan kanggo-loop). Yen lambda siji-line ngasilake soko, sampeyan ora kudu kalebu areturnpratelan. Nanging yen sampeyan nggunakake kurung kriting, sampeyan kudu kanthi tegas nyakup returnstatement, kaya sing sampeyan tindakake ing cara biasa.

Tuladha

Tuladha 1.

() -> {}
Conto paling prasaja. Lan sing paling ora ana gunane :), amarga ora nindakake apa-apa. Tuladha 2.

() -> ""
Conto liyane sing menarik. Ora njupuk apa-apa lan ngasilake string kosong ( returndiilangi, amarga ora perlu). Mangkene bab sing padha, nanging karo return:

() -> { 
    return ""; 
}
Tuladha 3. "Halo, Donya!" nggunakake lambdas

() -> System.out.println("Hello, World!")
Butuh apa-apa lan bali apa-apa (kita ora bisa sijine returnsadurunge telpon kanggo System.out.println(), amarga println()jinis bali cara iku void). Iku mung nuduhake salam. Iki becik kanggo implementasine saka Runnableantarmuka. Conto ing ngisor iki luwih lengkap:

public class Main { 
    public static void main(String[] args) { 
        new Thread(() -> System.out.println("Hello, World!")).start(); 
    } 
}
Utawa kaya iki:

public class Main { 
    public static void main(String[] args) { 
        Thread t = new Thread(() -> System.out.println("Hello, World!")); 
        t.start();
    } 
}
Utawa kita bisa nyimpen ekspresi lambda minangka Runnableobyek lan banjur ngirim menyang Threadkonstruktor:

public class Main { 
    public static void main(String[] args) { 
        Runnable runnable = () -> System.out.println("Hello, World!"); 
        Thread t = new Thread(runnable); 
        t.start(); 
    } 
}
Ayo dideleng kanthi cetha nalika ekspresi lambda disimpen ing variabel. Antarmuka Runnablengandhani yen obyek kasebut kudu duwe public void run()metode. Miturut antarmuka, runcara kasebut ora njupuk paramèter. Lan ora ngasilake apa-apa, yaiku jinis bali yaiku void. Mulane, kode iki bakal nggawe obyek kanthi cara sing ora njupuk utawa ngasilake apa-apa. Iki cocog banget karo metode Runnableantarmuka run(). Pramila kita bisa nyelehake ekspresi lambda iki ing Runnablevariabel.  Tuladha 4.

() -> 42
Maneh, ora butuh apa-apa, nanging ngasilake nomer 42. Ekspresi lambda kasebut bisa dilebokake ing Callablevariabel, amarga antarmuka iki mung ana siji cara sing katon kaya iki:

V call(),
endi  V jinis bali (ing kasus kita,  int). Dadi, kita bisa nyimpen ekspresi lambda kaya ing ngisor iki:

Callable<Integer> c = () -> 42;
Conto 5. A expression lambda nglibatno sawetara baris

() -> { 
    String[] helloWorld = {"Hello", "World!"}; 
    System.out.println(helloWorld[0]); 
    System.out.println(helloWorld[1]); 
}
Maneh, iki ekspresi lambda tanpa paramèter lan voidjinis bali (amarga ora ana returnstatement).  Tuladha 6

x -> x
Kene kita njupuk xvariabel lan bali. Elinga yen mung ana siji parameter, sampeyan bisa ngilangi tanda kurung ing sakubenge. Mangkene bab sing padha, nanging nganggo kurung:

(x) -> x
Lan ing ngisor iki conto kanthi pernyataan bali sing eksplisit:

x -> { 
    return x;
}
Utawa kaya iki nganggo tanda kurung lan pernyataan bali:

(x) -> { 
    return x;
}
Utawa kanthi indikasi eksplisit saka jinis kasebut (lan kanthi kurung):

(int x) -> x
Tuladha 7

x -> ++x
Kita njupuk xlan bali, nanging mung sawise nambah 1. Sampeyan bisa nulis ulang lambda kaya iki:

x -> x + 1
Ing kasus loro, kita ngilangi tanda kurung ing sakubenge parameter lan awak metode, bebarengan karo statement return, amarga padha opsional. Versi karo kurung lan statement bali diwenehi ing Conto 6. Conto 8

(x, y) -> x % y
We njupuk xlan ylan bali seko divisi saka xdening y. Ing kurung watara paramèter dibutuhake kene. Padha opsional mung yen ana mung siji parameter. Punika kanthi indikasi eksplisit babagan jinis:

(double x, int y) -> x % y
Tuladha 9

(Cat cat, String name, int age) -> {
    cat.setName(name); 
    cat.setAge(age); 
}
Kita njupuk Catobyek, Stringjeneng, lan umur int. Ing cara dhewe, kita nggunakake jeneng liwati lan umur kanggo nyetel variabel ing kucing. Amarga catobyek kita minangka jinis referensi, bakal diganti ing njaba ekspresi lambda (bakal entuk jeneng lan umur sing liwati). Mangkene versi sing rada rumit sing nggunakake lambda sing padha:

public class Main { 

    public static void main(String[] args) { 
        // Create a cat and display it to confirm that it is "empty" 
        Cat myCat = new Cat(); 
        System.out.println(myCat);
 
        // Create a lambda 
        Settable<Cat> s = (obj, name, age) -> { 
            obj.setName(name); 
            obj.setAge(age); 

        }; 

        // Call a method to which we pass the cat and lambda 
        changeEntity(myCat, s); 

        // Display the cat on the screen and see that its state has changed (it has a name and age) 
        System.out.println(myCat); 

    } 

    private static <T extends HasNameAndAge>  void changeEntity(T entity, Settable<T> s) { 
        s.set(entity, "Smokey", 3); 
    }
}

interface HasNameAndAge { 
    void setName(String name); 
    void setAge(int age); 
}

interface Settable<C extends HasNameAndAge> { 
    void set(C entity, String name, int age); 
}

class Cat implements HasNameAndAge { 
    private String name; 
    private int age; 

    @Override 
    public void setName(String name) { 
        this.name = name;
    }

    @Override
    public void setAge(int age) {
        this.age = age; 
    } 

    @Override
    public String toString() {
        return "Cat{" +
                "name='" + name + '\'' + 
                ", age=" + age + 
                '}';
    }
}
asil:

Cat{name='null', age=0}
Cat{name='Smokey', age=3}
Kaya sing sampeyan ngerteni, Catobyek kasebut duwe siji negara, banjur negara kasebut diganti sawise nggunakake ekspresi lambda. Ekspresi Lambda digabungake kanthi sampurna karo generik. Lan yen kita kudu nggawe Dogkelas sing uga ngleksanakake HasNameAndAge, mula kita bisa nindakake operasi sing padha ing metode Dogkasebut main() tanpa ngganti ekspresi lambda. Tugas 3. Tulis antarmuka fungsional kanthi cara sing njupuk nomer lan ngasilake nilai boolean. Tulis implementasi antarmuka kasebut minangka ekspresi lambda sing ngasilake bener yen nomer liwati bisa dibagi 13. Tugas 4.Tulis antarmuka fungsional kanthi cara sing njupuk rong senar lan uga ngasilake senar. Tulis implementasi antarmuka kaya ekspresi lambda sing ngasilake string sing luwih dawa. Tugas 5. Tulis antarmuka fungsional kanthi cara sing njupuk telung nomer floating-point: a, b, lan c lan uga ngasilake nomer floating-point. Tulis implementasine antarmuka kaya ekspresi lambda sing ngasilake diskriminan. Yen sampeyan lali, sing D = b^2 — 4ac. Tugas 6. Nggunakake antarmuka fungsi saka Tugas 5, nulis expression lambda sing ngasilake asil saka a * b^c. Panjelasan babagan ekspresi lambda ing basa Jawa. Kanthi conto lan tugas. Bagean 2
Komentar
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION