JavaRush /Java Blog /Random-TL /Sikat tungkol sa mga expression ng lambda sa Java. Sa mga...

Sikat tungkol sa mga expression ng lambda sa Java. Sa mga halimbawa at gawain. Bahagi 1

Nai-publish sa grupo
Para kanino ang artikulong ito?
  • Para sa mga nag-iisip na alam na nila ang Java Core, ngunit walang ideya tungkol sa mga expression ng lambda sa Java. O, marahil, may narinig ka na tungkol sa mga lambda, ngunit walang mga detalye.
  • para sa mga may kaunting pag-unawa sa mga expression ng lambda, ngunit natatakot at hindi pangkaraniwang gamitin ang mga ito.
Kung hindi ka nabibilang sa isa sa mga kategoryang ito, maaari mong makita ang artikulong ito na boring, mali, at sa pangkalahatan ay "hindi cool." Sa kasong ito, huwag mag-atubiling dumaan, o, kung bihasa ka sa paksa, magmungkahi sa mga komento kung paano ko mapapabuti o madagdagan ang artikulo. Ang materyal ay hindi nag-aangkin ng anumang pang-akademikong halaga, higit na hindi bago. Sa halip, sa kabaligtaran: sa loob nito ay susubukan kong ilarawan ang mga kumplikadong (para sa ilang) mga bagay nang simple hangga't maaari. Na-inspire akong magsulat sa pamamagitan ng kahilingang ipaliwanag ang stream api. Pinag-isipan ko ito at nagpasya na kung walang pag-unawa sa mga expression ng lambda, ang ilan sa aking mga halimbawa tungkol sa "mga stream" ay hindi mauunawaan. Kaya magsimula tayo sa lambdas. Sikat tungkol sa mga expression ng lambda sa Java.  Sa mga halimbawa at gawain.  Bahagi 1 - 1Anong kaalaman ang kinakailangan upang maunawaan ang artikulong ito:
  1. Pag-unawa sa object-oriented programming (mula rito ay tinutukoy bilang OOP), katulad ng:
    • kaalaman sa kung ano ang mga klase at bagay, ano ang pagkakaiba sa pagitan nila;
    • kaalaman sa kung ano ang mga interface, kung paano sila naiiba sa mga klase, ano ang koneksyon sa pagitan nila (mga interface at klase);
    • kaalaman sa kung ano ang isang pamamaraan, kung paano ito tawagan, kung ano ang isang abstract na pamamaraan (o isang pamamaraan na walang pagpapatupad), kung ano ang mga parameter/argumento ng isang pamamaraan, kung paano ipasa ang mga ito doon;
    • mga modifier sa pag-access, mga static na pamamaraan/variable, panghuling pamamaraan/variable;
    • inheritance (mga klase, interface, multiple inheritance ng mga interface).
  2. Kaalaman sa Java Core: generics, mga koleksyon (listahan), mga thread.
Well, simulan na natin.

Isang maliit na kasaysayan

Ang mga expression ng Lambda ay dumating sa Java mula sa functional programming, at doon mula sa matematika. Sa kalagitnaan ng ika-20 siglo sa Amerika, isang partikular na Alonzo Church ang nagtrabaho sa Princeton University, na mahilig sa matematika at lahat ng uri ng abstraction. Si Alonzo Church ang gumawa ng lambda calculus, na sa una ay isang set ng ilang abstract na ideya at walang kinalaman sa programming. Kasabay nito, ang mga mathematician tulad nina Alan Turing at John von Neumann ay nagtrabaho sa parehong Princeton University. Nagsama-sama ang lahat: Gumawa ang Simbahan ng lambda calculus system, binuo ni Turing ang kanyang abstract computing machine, na kilala ngayon bilang "Turing machine." Well, iminungkahi ni von Neumann ang isang diagram ng arkitektura ng mga computer, na naging batayan ng mga modernong computer (at ngayon ay tinatawag na "von Neumann architecture"). Sa oras na iyon, ang mga ideya ng Alonzo Church ay hindi nakakuha ng mas maraming katanyagan gaya ng gawain ng kanyang mga kasamahan (maliban sa larangan ng "dalisay" na matematika). Gayunpaman, pagkaraan ng ilang sandali, isang John McCarthy (nagtapos din sa Princeton University, sa oras ng kuwento - isang empleyado ng Massachusetts Institute of Technology) ay naging interesado sa mga ideya ng Simbahan. Batay sa kanila, noong 1958 nilikha niya ang unang functional programming language, Lisp. At makalipas ang 58 taon, ang mga ideya ng functional programming ay tumagas sa Java bilang numero 8. Wala pang 70 taon ang lumipas... Sa katunayan, hindi ito ang pinakamahabang panahon para sa paglalapat ng ideya sa matematika sa pagsasanay.

Ang kakanyahan

Ang isang lambda expression ay tulad ng isang function. Maaari mong isipin ito bilang isang regular na pamamaraan sa Java, ang pagkakaiba lamang ay maaari itong maipasa sa iba pang mga pamamaraan bilang isang argumento. Oo, naging posible na ipasa hindi lamang ang mga numero, string at pusa sa mga pamamaraan, kundi pati na rin ang iba pang mga pamamaraan! Kailan kaya natin ito kailangan? Halimbawa, kung gusto naming magpasa ng ilang callback. Kailangan natin ang pamamaraang tinatawag natin upang makatawag ng ibang paraan na ipinapasa natin dito. Iyon ay, upang magkaroon tayo ng pagkakataong magpadala ng isang callback sa ilang mga kaso, at isa pa sa iba. At ang aming pamamaraan, na tatanggap sa aming mga callback, ay tatawag sa kanila. Ang isang simpleng halimbawa ay ang pag-uuri. Sabihin nating sumulat tayo ng ilang uri ng nakakalito na pag-uuri na mukhang ganito:
public void mySuperSort() {
    // ... do something here
    if(compare(obj1, obj2) > 0)
    // ... and here we do something
}
Kung saan, iftinatawag namin ang pamamaraan compare(), ipasa doon ang dalawang bagay na aming ikinukumpara, at gusto naming malaman kung alin sa mga bagay na ito ang "mas malaki". Uunahin natin ang “mas” bago ang “mas maliit”. Sumulat ako ng "higit pa" sa mga quote dahil nagsusulat kami ng isang unibersal na pamamaraan na magagawang pag-uri-uriin hindi lamang sa pataas kundi pati na rin sa pababang pagkakasunud-sunod (sa kasong ito, "higit pa" ang magiging bagay na mahalagang mas maliit, at kabaliktaran) . Upang itakda ang panuntunan para sa eksaktong paraan kung paano namin gustong pag-uri-uriin, kailangan naming ipasa ito sa aming mySuperSort(). Sa kasong ito, kahit papaano ay makokontrol natin ang ating pamamaraan habang ito ay tinatawag. Siyempre, maaari kang magsulat ng dalawang magkahiwalay na paraan mySuperSortAsc()para sa mySuperSortDesc()pag-uuri sa pataas at pababang pagkakasunud-sunod. O ipasa ang ilang parameter sa loob ng pamamaraan (halimbawa, booleankung true, ayusin sa pataas na pagkakasunud-sunod, at kung falsesa pababang pagkakasunud-sunod). Ngunit paano kung nais nating pag-uri-uriin ang hindi ilang simpleng istraktura, ngunit, halimbawa, isang listahan ng mga string array? Paano mySuperSort()malalaman ng aming pamamaraan kung paano ayusin ang mga string array na ito? Sa laki? Sa kabuuang haba ng mga salita? Marahil ayon sa alpabeto, depende sa unang hilera sa array? Ngunit paano kung, sa ilang mga kaso, kailangan nating pag-uri-uriin ang isang listahan ng mga array ayon sa laki ng array, at sa ibang kaso, ayon sa kabuuang haba ng mga salita sa array? Sa tingin ko narinig mo na ang tungkol sa mga comparator at sa mga ganitong pagkakataon ay nagpapasa lang kami ng object ng comparator sa aming paraan ng pag-uuri, kung saan inilalarawan namin ang mga panuntunan kung saan gusto naming pagbukud-bukurin. Dahil ang karaniwang pamamaraan sort()ay ipinatupad sa parehong prinsipyo tulad ng , mySuperSort()sa mga halimbawa ay gagamitin ko ang pamantayan sort().
String[] array1 = {"Mother", "soap", "frame"};
String[] array2 = {"I", "Very", "I love", "java"};
String[] array3 = {"world", "work", "May"};

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[]> sortByWordsLength = 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);
Resulta:
  1. hinugasan ni nanay ang frame
  2. kapayapaan Labour maaaring
  3. Mahal ko talaga ang java
Dito ang mga array ay pinagsunod-sunod ayon sa bilang ng mga salita sa bawat array. Ang isang array na may mas kaunting mga salita ay itinuturing na "mas maliit". Iyon ang dahilan kung bakit ito ay dumating sa simula. Ang isa kung saan mayroong higit pang mga salita ay itinuturing na "higit pa" at nagtatapos sa dulo. Kung sort()ipapasa natin ang isa pang comparator sa method (sortByWordsLength), mag-iiba ang resulta :
  1. kapayapaan Labour maaaring
  2. hinugasan ni nanay ang frame
  3. Mahal ko talaga ang java
Ngayon ang mga array ay pinagsunod-sunod ayon sa kabuuang bilang ng mga titik sa mga salita ng naturang array. Sa unang kaso mayroong 10 letra, sa pangalawang 12, at sa pangatlo 15. Kung gagamit lamang tayo ng isang comparator, hindi tayo makakagawa ng hiwalay na variable para dito, ngunit lumikha lamang ng object ng isang anonymous na klase sa mismong bahagi ng oras ng pagtawag sa pamamaraan sort(). Tulad niyan:
String[] array1 = {"Mother", "soap", "frame"};
String[] array2 = {"I", "Very", "I love", "java"};
String[] array3 = {"world", "work", "May"};

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;
    }
});
Ang resulta ay magiging katulad ng sa unang kaso. Gawain 1 . Isulat muli ang halimbawang ito upang pag-uri-uriin nito ang mga array hindi sa pataas na pagkakasunud-sunod ng bilang ng mga salita sa array, ngunit sa pababang pagkakasunud-sunod. Alam na natin ang lahat ng ito. Alam namin kung paano ipasa ang mga bagay sa mga pamamaraan, maaari naming ipasa ito o ang bagay na iyon sa isang pamamaraan depende sa kung ano ang kailangan namin sa sandaling ito, at sa loob ng pamamaraan kung saan ipinapasa namin ang isang bagay, ang pamamaraan kung saan isinulat namin ang pagpapatupad ay tatawagin . Ang tanong ay lumitaw: ano ang kinalaman ng mga expression ng lambda dito? Dahil ang lambda ay isang bagay na naglalaman ng eksaktong isang paraan. Ito ay tulad ng isang object object. Isang paraan na nakabalot sa isang bagay. Mayroon lang silang bahagyang hindi pangkaraniwang syntax (ngunit higit pa sa paglaon). Tingnan natin muli ang entry na ito
arrays.sort(new Comparator<String[]>() {
    @Override
    public int compare(String[] o1, String[] o2) {
        return o1.length - o2.length;
    }
});
Dito kinukuha namin ang aming listahan arraysat tinawag ang pamamaraan nito sort(), kung saan ipinapasa namin ang isang comparator object na may isang solong pamamaraan compare()(hindi mahalaga sa amin kung ano ang tawag dito, dahil isa lang ito sa bagay na ito, hindi namin ito palalampasin). Ang pamamaraang ito ay tumatagal ng dalawang mga parameter, na kung saan gagana namin sa susunod. Kung nagtatrabaho ka sa IntelliJ IDEA , malamang na nakita mo kung paano ito nag-aalok sa iyo ng code na ito upang makabuluhang paikliin:
arrays.sort((o1, o2) -> o1.length - o2.length);
Iyon ay kung paano ang anim na linya ay naging isang maikli. 6 na linya ang muling isinulat sa isang maikli. May nawala, ngunit ginagarantiya ko na walang mahalagang nawala, at ang code na ito ay gagana nang eksakto katulad ng sa isang hindi kilalang klase. Gawain 2 . Alamin kung paano muling isulat ang solusyon sa problema 1 gamit ang mga lambdas (bilang huling paraan, hilingin sa IntelliJ IDEA na gawing lambda ang iyong anonymous na klase).

Pag-usapan natin ang tungkol sa mga interface

Karaniwan, ang isang interface ay isang listahan lamang ng mga abstract na pamamaraan. Kapag lumikha kami ng isang klase at sinabi na ito ay magpapatupad ng ilang uri ng interface, dapat naming isulat sa aming klase ang pagpapatupad ng mga pamamaraan na nakalista sa interface (o, bilang isang huling paraan, huwag isulat ito, ngunit gawing abstract ang klase ). Mayroong mga interface na may maraming iba't ibang mga pamamaraan (halimbawa List), may mga interface na may isang paraan lamang (halimbawa, ang parehong Comparator o Runnable). May mga interface na walang iisang paraan (tinatawag na mga marker interface, halimbawa Serializable). Ang mga interface na mayroon lamang isang paraan ay tinatawag ding mga functional na interface . Sa Java 8 sila ay minarkahan pa ng isang espesyal na @FunctionalInterface annotation . Ito ay mga interface na may isang solong pamamaraan na angkop para sa paggamit ng mga expression ng lambda. Tulad ng sinabi ko sa itaas, ang isang lambda expression ay isang paraan na nakabalot sa isang bagay. At kapag dumaan tayo sa ganoong bagay sa isang lugar, sa katunayan, ipinapasa natin ang isang solong pamamaraan na ito. Lumalabas na hindi mahalaga sa amin kung ano ang tawag sa pamamaraang ito. Ang mahalaga lang sa amin ay ang mga parameter na kinukuha ng pamamaraang ito, at, sa katunayan, ang code ng pamamaraan mismo. Ang isang lambda expression ay, mahalagang. pagpapatupad ng isang functional na interface. Kung saan nakikita natin ang isang interface na may isang paraan, nangangahulugan ito na maaari nating muling isulat ang gayong hindi kilalang klase gamit ang isang lambda. Kung ang interface ay may higit pa/mas kaunti sa isang paraan, ang lambda expression ay hindi angkop sa amin, at gagamit kami ng hindi kilalang klase, o kahit na isang regular. Oras na para maghukay sa mga lambdas. :)

Syntax

Ang pangkalahatang syntax ay ganito:
(параметры) -> {тело метода}
Iyon ay, mga panaklong, sa loob ng mga ito ay ang mga parameter ng pamamaraan, isang "arrow" (ito ay dalawang magkasunod na mga character: minus at mas malaki), pagkatapos kung saan ang katawan ng pamamaraan ay nasa mga kulot na braces, gaya ng lagi. Ang mga parameter ay tumutugma sa mga tinukoy sa interface kapag inilalarawan ang pamamaraan. Kung ang uri ng mga variable ay maaaring malinaw na tukuyin ng compiler (sa aming kaso, ito ay tiyak na kilala na kami ay nagtatrabaho sa mga arrays ng mga string, dahil ito Listay nai-type nang tumpak sa pamamagitan ng arrays ng mga string), kung gayon ang uri ng mga variable ay String[]hindi kailangan isulat.
Kung hindi ka sigurado, tukuyin ang uri, at iha-highlight ito ng IDEA sa kulay abo kung hindi ito kailangan.
Maaari kang magbasa ng higit pa sa Oracle tutorial , halimbawa. Ito ay tinatawag na "target na pagta-type" . Maaari kang magbigay ng anumang mga pangalan sa mga variable, hindi kinakailangan ang mga tinukoy sa interface. Kung walang mga parameter, pagkatapos ay panaklong lamang. Kung mayroon lamang isang parameter, ang pangalan ng variable na walang panaklong. Inayos namin ang mga parameter, ngayon tungkol sa katawan ng lambda expression mismo. Sa loob ng mga kulot na braces, isulat ang code bilang para sa isang regular na pamamaraan. Kung ang iyong buong code ay binubuo lamang ng isang linya, hindi mo na kailangang magsulat ng mga kulot na brace (tulad ng mga if at loop). Kung may ibinalik ang iyong lambda, ngunit ang katawan nito ay binubuo ng isang linya, returnhindi na kailangang magsulat. Ngunit kung mayroon kang mga kulot na braces, kung gayon, tulad ng sa karaniwang pamamaraan, kailangan mong tahasang isulat return.

Mga halimbawa

Halimbawa 1.
() -> {}
Ang pinakasimpleng opsyon. At ang pinaka walang kabuluhan :) Dahil wala itong ginagawa. Halimbawa 2.
() -> ""
Gayundin isang kawili-wiling pagpipilian. Wala itong tinatanggap at nagbabalik ng walang laman na string ( returntinanggal bilang hindi kailangan). Pareho, ngunit may return:
() -> {
    return "";
}
Halimbawa 3. Hello world gamit ang lambdas
() -> System.out.println("Hello world!")
Walang natatanggap, walang ibinabalik (hindi namin mailalagay returnbago ang tawag System.out.println(), dahil ang uri ng pagbabalik sa pamamaraan println() — void), ay nagpapakita lamang ng inskripsyon sa screen. Tamang-tama para sa pagpapatupad ng interface Runnable. Ang parehong halimbawa ay mas kumpleto:
public class Main {
    public static void main(String[] args) {
        new Thread(() -> System.out.println("Hello world!")).start();
    }
}
O tulad nito:
public class Main {
    public static void main(String[] args) {
        Thread t = new Thread(() -> System.out.println("Hello world!"));
        t.start();
    }
}
O maaari nating i-save ang lambda expression bilang isang object ng uri Runnable, at pagkatapos ay ipasa ito sa constructor thread’а:
public class Main {
    public static void main(String[] args) {
        Runnable runnable = () -> System.out.println("Hello world!");
        Thread t = new Thread(runnable);
        t.start();
    }
}
Tingnan natin ang sandali ng pag-save ng lambda expression sa isang variable. Ang interface Runnableay nagsasabi sa amin na ang mga bagay nito ay dapat na may isang pamamaraan public void run(). Ayon sa interface, ang run method ay hindi tumatanggap ng anuman bilang mga parameter. At hindi ito nagbabalik ng anuman (void). Samakatuwid, kapag nagsusulat sa ganitong paraan, ang isang bagay ay malilikha gamit ang ilang pamamaraan na hindi tumatanggap o nagbabalik ng anuman. Na medyo pare - pareho sa paraan run()sa interface Runnable. Iyon ang dahilan kung bakit nagawa naming ilagay ang lambda expression na ito sa isang variable tulad ng Runnable. Halimbawa 4
() -> 42
Muli, hindi ito tumatanggap ng anuman, ngunit ibinabalik ang numero 42. Ang lambda expression na ito ay maaaring ilagay sa isang variable ng uri Callable, dahil ang interface na ito ay tumutukoy lamang sa isang paraan, na mukhang ganito:
V call(),
nasaan Vang uri ng return value (sa aming kaso int). Alinsunod dito, maaari tayong mag-imbak ng gayong lambda na expression tulad ng sumusunod:
Callable<Integer> c = () -> 42;
Halimbawa 5. Lambda sa ilang linya
() -> {
    String[] helloWorld = {"Hello", "world!"};
    System.out.println(helloWorld[0]);
    System.out.println(helloWorld[1]);
}
Muli, ito ay isang lambda expression na walang mga parameter at ang uri ng pagbabalik nito void(dahil walang return). Halimbawa 6
x -> x
Dito kami kumuha ng isang bagay sa isang variable хat ibalik ito. Pakitandaan na kung isang parameter lang ang tinatanggap, hindi na kailangang isulat ang mga panaklong sa paligid nito. Pareho, ngunit may mga bracket:
(x) -> x
At narito ang opsyon na may tahasang isa return:
x -> {
    return x;
}
O tulad nito, na may mga bracket at return:
(x) -> {
    return x;
}
O may tahasang indikasyon ng uri (at, nang naaayon, may mga panaklong):
(int x) -> x
Halimbawa 7
x -> ++x
Tinatanggap namin ito хat ibinabalik, ngunit para sa 1higit pa. Maaari mo ring muling isulat ito tulad nito:
x -> x + 1
Sa parehong mga kaso, hindi kami nagsasaad ng mga panaklong sa paligid ng parameter, katawan ng pamamaraan, at salita return, dahil hindi ito kinakailangan. Ang mga opsyon na may mga bracket at return ay inilarawan sa halimbawa 6. Halimbawa 8
(x, y) -> x % y
Tinatanggap namin ang ilan хat у, ibabalik ang natitira sa dibisyon xsa pamamagitan ng y. Ang mga panaklong sa paligid ng mga parameter ay kinakailangan na dito. Opsyonal lang ang mga ito kapag may isang parameter lang. Tulad nito na may tahasang indikasyon ng mga uri:
(double x, int y) -> x % y
Halimbawa 9
(Cat cat, String name, int age) -> {
    cat.setName(name);
    cat.setAge(age);
}
Tumatanggap kami ng Cat object, isang string na may pangalan at isang integer na edad. Sa mismong pamamaraan, itinakda namin ang ipinasa na pangalan at edad sa Pusa. catDahil ang aming variable ay isang uri ng sanggunian, ang Cat object sa labas ng lambda expression ay magbabago (tatanggap nito ang pangalan at edad na ipinasa sa loob). Medyo mas kumplikadong bersyon na gumagamit ng katulad na lambda:
public class Main {
    public static void main(String[] args) {
        // create a cat and print to the screen to make sure it's "blank"
        Cat myCat = new Cat();
        System.out.println(myCat);

        // create lambda
        Settable<Cat> s = (obj, name, age) -> {
            obj.setName(name);
            obj.setAge(age);
        };

        // call the method, to which we pass the cat and the lambda
        changeEntity(myCat, s);
        // display on the screen and see that the state of the cat has changed (has a name and age)
        System.out.println(myCat);
    }

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

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

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

class Cat implements WithNameAndAge {
    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 +
                '}';
    }
}
Resulta: Cat{name='null', age=0} Cat{name='Murzik', age=3} Gaya ng nakikita mo, sa una ang Cat object ay may isang estado, ngunit pagkatapos gamitin ang lambda expression, nagbago ang estado . Ang mga expression ng Lambda ay mahusay na gumagana sa mga generic. At kung kailangan nating lumikha ng isang class Dog, halimbawa, ipapatupad din iyon WithNameAndAge, kung gayon sa pamamaraan ay main()maaari nating gawin ang parehong mga operasyon sa Aso, nang hindi binabago ang mismong lambda na expression. Gawain 3 . Sumulat ng functional na interface na may paraan na kumukuha ng numero at nagbabalik ng Boolean value. Sumulat ng pagpapatupad ng naturang interface sa anyo ng isang lambda expression na nagbabalik truekung ang naipasa na numero ay nahahati sa 13 nang walang natitira.Gawain 4 . Sumulat ng isang functional na interface na may isang paraan na tumatagal ng dalawang mga string at nagbabalik ng parehong string. Sumulat ng pagpapatupad ng naturang interface sa anyo ng isang lambda na nagbabalik ng pinakamahabang string. Gawain 5 . Sumulat ng functional interface na may paraan na tumatanggap ng tatlong fractional na numero: a, b, cat ibinabalik ang parehong fractional number. Sumulat ng pagpapatupad ng naturang interface sa anyo ng lambda expression na nagbabalik ng discriminant. Sino ang nakalimutan, D = b^2 - 4ac . Gawain 6 . Gamit ang functional na interface mula sa gawain 5, magsulat ng lambda expression na nagbabalik ng resulta ng operasyon a * b^c. Sikat tungkol sa mga expression ng lambda sa Java. Sa mga halimbawa at gawain. Bahagi 2.
Mga komento
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION