7,540
edits
Changes
Java-mis
,no edit summary
=Java λ=
==List-forEach()==
...
</source>
Ez a '''Consumer<? super T>''' generikus interfész implementációt várja paraméterként, ahol a T a List-ben lévő lista elemek típusa. Valójában a A T listaelemek bármilyen leszármazottját elfogadja. A Láthatjuk az implementációból hogy a forEach metódus az összes listaelemen végigmegy, és minden egyes listaelemre meghívja a Consumer<T> implementáció '''accept()''' metódusát. Az A lista elemeket a saját osztály példányának a példány változójából szedi (vagyis ha van egy ArrayList típusú objektumunk, akkor az maga tárolja a lista elemeket egy belső változójában). A Consumer interfész implementáción múlik, hogy mit fog csinálni az adott listaelemmel. A Consumer implementáció (Consumer<? super T> action) csak egy cső, amibe felülről be tudunk dobni egy T elemet és kidob alul egy R elemet (jelen esetben nincs R elem, mert void típusú a Funkcionális függvény). Tehát az implementációnak nincs állapota. Kap egy inputot és generál belőle egy outputot.
<br><br>
}}
<br><br>
Nézzünk egy lehetséges implementációt:
<source lang="java">
public class MyConstumer implements Consumer<String>{
@Override
public void accept(String t) {
System.out.println(t);
}
}
</source>
A MyConsumer osztály implementálja a Consumer interfész egyetlen metódusát, az accept-et, egy String-et vár inputba és nem ad vissza semmit.
<br><br>
Ennek az implementációs osztálynak ez lenne egy lehetséges felhasználása:
<source lang="java">
public static void main(String[] args) {
List<String> items = new ArrayList<>();
items.add("A");
items.add("B");
items.add("C");
items.add("D");
items.add("E");
Consumer<String> myConsumer = new MyConstumer();
items.forEach(myConsumer);
}
</source>
<br><br>
Azonban Java8-tól kezdve bevezették a λ kifejezéseket, mivel név nélküli inline függvény implementációkat készíthetünk, ezek tulajdonképpen input és output paraméterrel rendelkező kód blokkok az alábbi szintaxissal (alább három kül. példa)
<pre>
parameter -> expression
(parameter1, parameter2) -> expression
(parameter1, parameter2) -> { code block }
</pre>
<br><br>
Az előző példa Lambda alakja a következő lenne:
<source lang="java">
Consumer<String> myConsumer = item -> System.out.println(item);
items.forEach(myConsumer);
</source>
<source lang="java">
items.forEach(item->System.out.println(item));
</source>
{{note|Az item kívülről nézve nem értelmezhető. Értelmet csak a forEach belsejében nyer. A lambad kifejezés csak egy állapot nélküli transzformációs függvény, ami inputnak megkapja az '''item'' nevű változót és csinál vele valamit:
<br>
<br>
Ez egy statikus metódus referencia, amivel azt mondjuk meg, hogy a Consumer implementációja a System.out.print(T) metódust fogja meghívni. A lényeg, hogy egy argumentumos legyen a megadott metódus és fel tudjon dolgozni T lista típusú elemet.
<br>
<br>
==Példa 2: saját implementáció==
Az alábbi osztálynak van egy darab osztály változója (variable1) és van egy darab metódusa: processVariable. Ez a metódus egy funkcionális interfészt vár input paraméterként.
<source lang="java">
package hu.otp.auth.loginHelper.util;
import java.util.function.Function;
public class MyLambadClass {
private String variable1;
public MyLambadClass(String a) {
this.variable1 = a;
}
public void processVariable(Function<String, Integer> fn) {
Integer length = fn.apply(variable1);
System.out.println(length.toString());
}
}
</source>
A processVariable belsejében meghívja a funkcionális interfész '''apply()''' metódusát. (Definiálhattunk volna magunknak saját funkcionális interfész típust, mi most itt egy gyári típust használunk). Az apply-nak átadja a saját osztály változóját, majd az apply által visszaadott Integer-t kiírja a sysout-ra. Az hogy az apply belsejében hogy áll elő az Ingerer és hogy mit csinál a bemenő String paraméterrel teljes egészében az apply implementációra van bízva.
<br>
Nézzünk meg egy lehetséges implementációt:
<source lang="java">
public static void main(String[] args) {
MyLambadClass myLambadClass = new MyLambadClass("adam");
myLambadClass.processVariable(var1 -> { return Integer.valueOf(var1.length()); });
}
</source>
Ebből az apply lambad kifejezéssel történő inline implementációja az alábbi:
<pre>
var1 -> { return Integer.valueOf(var1.length()); }
</pre>
Ami nem csinál mást, mint visszaadja a kapott string hosszát. Kívülről nézve a var1 nem értelmezhető, az mindig a lamdát futtató osztály egy osztály változója, kívülről nem megadható.
<br>
<br>
==Példa 3: CompletionStage.thenCompose()==
==thenCompose()=Mi is ez?===
<source lang="java">
method1().thenCompose(var1 -> method2(var1))
.whenComplete((result, error) -> { ...}
</source>
A '''thenCompose''' szignatúrája az alábbi:
<source lang="java">
<br>
<br>
Tehát a '''thenCompose(..)''' vár egy '''Function''' interfész implementációt és belül meg fogja hívni az '''apply(..)''' metódusát, aminek át fog adni egy T típusú változót, és R típusú változót fog visszavárni visszatérési értékként. Hogy ezt megértsük, nézzük Nézzük meg a '''thenCompose''' implementációját:
<source lang=java>
try {
}
</source>
<source lang="java">
...
.thenCompose(var1 -> method2{ ... //Create a future with string inside new CompletableFuture<String> future = new CompletableFuture<String>(); future.complete("adam"); return future; }) .thenCompose(var1 -> { System.out.println(var1); //will print "adam" ... })
...
</source>
{{note|Tehát az apply(..) inline implementációja csak egy cső, amibe a lambda kifejezések láncban hívásakor mindig a Funkcionális interfész definíciójában szereplő T thenCompose() bedob egy változót és R input és output típusok közlekednek automatikusanvisszavár egy végeredményt. Annak ellenére, hogy minden egyes inline implementáció A változó itt is a láncban egy <pre>? extends CompletionStage<U>></pre> -el kell visszatérjen, ebből saját példány változója (történetesen az U-t fogja megkapni a következő inline implementáció méghozzá ezért: előző futás eredménye)}}
.thenCompose(var2 -> method3(var2))
</source>