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. Gowy 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 MouseAdapter
we 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 b
float 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 bolarvoid
).
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.Runnable
funksional 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. Runnable
Mysal üç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 Runnable
synp 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 };
@FunctionalInterface
Java 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. @FunctionalInterface
yglan 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: AkymyThread
iki 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. ActionListener
UI 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 Predicate
synag 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*x
usula 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üň ulanylmagydyrthis
. Anonim synplar üçin '' açar söz, this
nä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
GO TO FULL VERSION