JavaRush /Java Blog /Random-TK /Lambda mysallar bilen aňlatmalar

Lambda mysallar bilen aňlatmalar

Toparda çap edildi
Java başda düýbünden obýekte gönükdirilen dil. Ilkinji görnüşlerden başga, Java-daky hemme zat obýektdir. Hatda massiwler hem obýektdir. Her synpyň mysallary obýektlerdir. Funksiýany aýratyn kesgitlemek üçin ýekeje mümkinçilik ýok (synpyň daşynda - takmynan terjime. ) Bir usuly argument hökmünde geçirmäge ýa-da başga bir usulyň netijesinde usul usulyny yzyna gaýtarmaga ýol ýok. Bu şeýle. Javaöne bu Java 8-den öň bolupdy. Lambda mysallar bilen aňlatmalar - 1Gowy köne Swing döwründen bäri käbir funksiýalary haýsydyr bir usula geçirmek zerur bolanda anonim synplary ýazmalydy. Mysal üçin, hadysany dolandyryjy goşmagyň görnüşi:
someObject.addMouseListener(new MouseAdapter() {
            public void mouseClicked(MouseEvent e) {

                //Event listener implementation goes here...

            }
        });
Bu ýerde syçanjygyň wakasyny diňleýjä käbir kod goşmak isleýäris. Anonim synpy kesgitledik MouseAdapterwe derrew ondan bir obýekt döretdik. Şeýlelik bilen, goşmaça funksiýany geçdik addMouseListener. Gysgaça aýdylanda, argument arkaly Java-da ýönekeý bir usuly (funksiýany) geçirmek aňsat däl. Bu çäklendirme Java 8 döredijileri dil spesifikasiýasyna Lambda aňlatmalary ýaly aýratynlyk goşmaga mejbur etdi.

Java näme üçin Lambda aňlatmalaryna mätäç?

Ilkibaşdan Java dili kän bir ösmedi, Annotasiýa, Generika we ş.m. ýaly zatlardan başga zatlar, ilki bilen Java hemişe obýekte öwrüldi. JavaScript ýaly funksional diller bilen işläniňizden soň, Java-yň berk obýekte we berk ýazylýandygyna düşünip bilersiňiz. Java-da funksiýalar gerek däl. Java dünýäsinde özleri tapyp bolmaýar. Funksional programmirleme dillerinde funksiýalar birinji orunda durýar. Olar özbaşdak bar. Olary üýtgeýänlere belläp, argumentlerden beýleki funksiýalara geçirip bilersiňiz. JavaScript funksional programmirleme dilleriniň iň gowy mysallaryndan biridir. Internetde JavaScript-iň işleýiş dili hökmünde peýdalary barada jikme-jik makalalary tapyp bilersiňiz. Funksional dillerde ýapyş ýaly güýçli gurallar bar, bu programmalary ýazmagyň adaty usullaryndan birnäçe artykmaçlygy üpjün edýär. .Apylmak, oňa gurşalan gurşaw bilen funksiýa - funksiýanyň ýerli däl üýtgeýänlerine salgylanmalary saklaýan tablisadyr. Java-da ýapylmalary Lambda aňlatmalary arkaly simulasiýa edip bolýar. Elbetde, ýapylmalar bilen Lambda aňlatmalarynyň arasynda tapawutlar bar, kiçijik däl, ýöne lambda aňlatmalary ýapylmagyň gowy alternatiwasydyr. Stiw gegge özüniň gülkünç we gülkünç blogynda Java dünýäsiniň atlar (subýektler, obýektler - takmynan terjime ) bilen berk baglanyşyklydygyny suratlandyrýar. Blogyny okamadyk bolsaňyz, maslahat berýärin. Lambda sözleriniň Java-a goşulmagynyň takyk sebäbini gülkünç we gyzykly görnüşde suratlandyrýar. Lambda aňlatmalary, Java-a şunça wagt bäri ýitip gelýän funksiýany getirýär. Lambda aňlatmalary, edil obýektler ýaly dile işleýär. Bu 100% dogry bolmasa-da, Lambda sözleriniň ýapylmaýandygyna garamazdan şuňa meňzeş mümkinçilikleri üpjün edýändigini görüp bilersiňiz. Funksiýa dilinde lambda aňlatmalary funksiýalardyr; emma Java-da lambda aňlatmalary obýektler bilen aňladylýar we funksional interfeýs diýilýän belli bir obýekt görnüşi bilen baglanyşykly bolmaly. Indiki onuň nämedigine serederis. Mario Fuskonyň “Näme üçin Java-da Lambda aňlatmasy gerek” atly makalasy häzirki zaman dilleriniň näme üçin ýapmak mümkinçiliklerine mätäçdigini jikme-jik beýan edýär.

Lambda aňlatmalary bilen tanyşlyk

Lambda aňlatmalary anonim funksiýalardyr (Java üçin 100% dogry kesgitleme bolup bilmez, ýöne belli bir derejede aýdyňlyk getirýär). Plyönekeý söz bilen aýdylanda, bu beýannama bermezden usul. üýtgeýjilere, gymmaty we adyny yzyna gaýtarmazdan. Gysgaça aýdanyňda, size bir usul ýazmaga we derrew ulanmaga mümkinçilik berýär. Esasanam bir gezeklik usul çagyryşy bolan ýagdaýynda peýdalydyr, sebäbi synp döretmezden usuly yglan etmek we ýazmak üçin sarp edilýän wagty gysgaldýar. Java-daky Lambda aňlatmalary adatça aşakdaky sintaksislere eýe (аргументы) -> (тело). Mysal üçin:
(арг1, арг2...) -> { тело }

(тип1 арг1, тип2 арг2...) -> { тело }
Aşakda Lambda hakyky sözlemleriniň käbir mysallary bar:
(int a, int b) -> {  return a + b; }

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

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

() -> 42

() -> { return 3.1415 };

Lambda aňlatmalarynyň gurluşy

Lambda aňlatmalarynyň gurluşyny öwreneliň:
  • Lambda aňlatmalarynda 0 ýa-da has köp giriş parametrleri bolup biler.
  • Parametrleriň görnüşini aç-açan kesgitläp bolýar ýa-da kontekstden alyp bolýar. Mysal üçin ( int a) şeýle ýazylyp bilner ( a)
  • Parametrler gabygyň içine salynýar we dykgat bilen bölünýär. Mysal üçin ( a, b) ýa-da ( ) int a, int býa-da ( String a,, )int bfloat c
  • Parametrler ýok bolsa, boş gabygy ulanmaly. Mysal üçin() -> 42
  • Diňe bir parametr bar bolsa, görnüşi aç-açan görkezilmedik bolsa, gabygy aýryp bolýar. Mysal:a -> return a*a
  • Lambda aňlatmasynyň göwresinde 0 ýa-da has köp aňlatma bolup biler.
  • Beden bir sözlemden ybarat bolsa, egri ýaýlar bilen gurşalanok we açar söz bolmasa yzyna gaýtaryş bahasy kesgitlenip bilner return.
  • Otherwiseogsam, egrilen ýaýlar talap edilýär (kod bloky) we yzyna gaýtaryş gymmaty açar söz ulanyp ahyrynda görkezilmelidir return(ýogsam gaýdyp beriş görnüşi bolar void).

Funksiýa interfeýsi näme

Java-da Marker interfeýsleri usullary ýa-da meýdanlary yglan etmezden interfeýslerdir. Başgaça aýdylanda, token interfeýsleri boş interfeýslerdir. Şonuň ýaly-da, Funksional interfeýsler, diňe yglan edilen abstrakt usul bilen interfeýslerdir. java.lang.Runnablefunksional interfeýsiň mysalydyr. Diňe bir usuly yglan edýär void run(). Şeýle hem interfeýs bar ActionListener- işleýär. Öň funksional interfeýsi amala aşyrýan obýektleri döretmek üçin anonim synplary ulanmaly bolýardyk. Lambda sözleri bilen hemme zat has ýönekeýleşdi. Her lambda aňlatmasy käbir funksional interfeýs bilen doly baglanyşykly bolup biler. RunnableMysal üçin, aşakdaky mysalda görkezilişi ýaly interfeýs üçin salgylanma döredip bilersiňiz :
Runnable r = () -> System.out.println("hello world");
Funksiýa interfeýsini görkezmedik wagtymyz bu görnüş öwrülişi elmydama aç-açan amala aşyrylýar:
new Thread(
    () -> System.out.println("hello world")
).start();
Aboveokardaky mysalda, düzüji awtomatiki usulda Runnablesynp konstruktoryndan interfeýsiň ýerine ýetirilmegi hökmünde lambda aňlatmasyny döredýär Thread: public Thread(Runnable r) { }. Ine, lambda aňlatmalarynyň we degişli funksional interfeýsleriň käbir mysallary:
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 };
@FunctionalInterfaceJava 8 spesifikasiýasyna laýyklykda Java 8-de goşulan düşündiriş, yglan edilen interfeýsiň işleýändigini ýa-da ýokdugyny barlaýar. Mundan başga-da, Java 8 Lambda aňlatmalary bilen ulanmak üçin birnäçe taýýar funksional interfeýsleri öz içine alýar. @FunctionalInterfaceyglan edilen interfeýs işlemeýän bolsa, düzmek ýalňyşlygyny atar. Aşakda funksional interfeýsi kesgitlemegiň mysaly:
@FunctionalInterface
public interface WorkerInterface {

    public void doSomeWork();

}
Kesgitlemäniň görkezişi ýaly, işleýän interfeýsde diňe bir abstrakt usul bolup biler. Başga bir abstrakt usul goşjak bolsaňyz, düzmek ýalňyşlygy ýüze çykar. Mysal:
@FunctionalInterface
public interface WorkerInterface {

    public void doSomeWork();

    public void doSomeMoreWork();

}
Roralňyşlyk
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") );
    }

}
Netije:
Worker вызван через анонимный класс
Worker вызван через Lambda
Bu ýerde öz funksional interfeýsimizi kesgitledik we lambda aňlatmasyny ulandyk. Usul execute()lambda aňlatmalaryny argument hökmünde kabul etmäge ukyply.

Lambda aňlatmalaryna mysallar

Lambda aňlatmalaryna düşünmegiň iň gowy usuly birnäçe mysallara göz aýlamakdyr: Akymy Threadiki görnüşde başlap bolar:
// 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();
Java 8-de hadysalary dolandyrmak Lambda aňlatmalary arkaly hem edilip bilner. ActionListenerUI komponentine hadysalary işleýjini goşmagyň iki usuly bar :
// 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!");
});
Berlen massiwiň ähli elementlerini görkezmegiň ýönekeý mysaly. Lambda aňlatmasyny ulanmagyň birden köp usulynyň bardygyny unutmaň. Aşakda ok sintaksisini ulanyp, adaty usulda lambda aňlatmasyny döredýäris, şeýle hem (::)Java 8-de adaty usuly lambda aňlatmasyna öwürýän goşa içege operatory ulanýarys:
// 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);
Aşakdaky mysalda Predicatesynag döretmek we şol synagdan geçýän zatlary çap etmek üçin funksional interfeýsi ulanýarys. Şeýlelik bilen, lambda aňlatmalaryna logika goýup we şoňa esaslanyp zatlar edip bilersiňiz.
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();
    }

}
Netije:
Выводит все числа: 1 2 3 4 5 6 7
Не выводит ни одного числа:
Вывод четных чисел: 2 4 6
Вывод нечетных чисел: 1 3 5 7
Вывод чисел больше 5: 6 7
Lambda aňlatmalary bilen gyzyklanyp, sanawyň her elementiniň kwadratyny görkezip bilersiňiz. stream()Adaty sanawy akymlara öwürmek üçin usuly ulanýandygymyza üns beriň . Java 8 ajaýyp synpy üpjün edýär Stream( java.util.stream.Stream). Onda lambda aňlatmalaryny ulanyp boljak birnäçe peýdaly usul bar. Lambda aňlatmasyny akymdaky ähli elementlere ulanýan x -> x*xusula geçirýäris . Ondan soň sanawyň ähli elementlerini çap etmek üçin map()ulanýarys .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);
Sanaw berilende, sanawyň ähli elementleriniň kwadratlarynyň jemini çap etmeli. Lambda aňlatmalary, diňe bir setir kod ýazmak arkaly size ýetmäge mümkinçilik berýär. Bu mysalda konwolýasiýa (azaltmak) usuly ulanylýar reduce(). Her elementi kwadratlamak üçin bir usul ulanýarys map(), soňra reduce()ähli elementleri bir sana bölmek usulyny ulanýarys.
// 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 aňlatmalary bilen anonim synplaryň arasyndaky tapawut

Esasy tapawut, açar sözüň ulanylmagydyr this. Anonim synplar üçin '' açar söz, thisnäbelli synpyň obýektini aňladýar, lambda aňlatmasynda ' this' lambda aňlatmasy ulanylýan synpyň obýektini aňladýar. Başga bir tapawut, olaryň düzüliş usulydyr. Java lambda aňlatmalaryny düzýär we olary synp usullaryna öwürýär private. Bu dinamiki usul bilen baglanyşdyrmak üçin Java 7-de girizilen çagyrylan görkezmäni ulanýar. Tal Weiss öz blogynda Java-nyň lambda aňlatmalaryny bytekoda nädip düzýändigini düşündirdi

Netije

Mark Reinhold (Oracle-yň baş arhitektory) Lambda diýip atlandyran programma modelinde bolup geçen iň möhüm üýtgeşmäni, hatda generiklerden has möhümdir. Ol dogry bolmaly, sebäbi ... Java programmaçylaryna her kimiň garaşýan funksional programmirleme dil mümkinçiliklerini berýär. Wirtual giňeltmek usullary ýaly täzelikler bilen bir hatarda Lambda aňlatmalary size ýokary hilli kod ýazmaga mümkinçilik berýär. Bu makala size Java 8-iň kapotynyň aşagynda bir göz aýlady diýip umyt edýärin.
Teswirler
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION