Functional interface @FunctionalInterface public interface Listener { public void onEvent(Event e); } @FunctionalInterface public interface Operator { public int process(int a, int b); } @FunctionalInterface public interface Runnable { public void run(); }
9
Lambda kifejezések • Lambda expression (nem pedig lambda type) • A háttérben egy functional interface van • FunctInterface f = … lambda expression...
• Anonymous function or function literal • metódus, amire a referenciát tárolhatjuk átadhatjuk
• Hol hasznos? • Anonim osztályok helyett • Runnable, Callable, Comparator, Collection műveletek • Paraméterezet viselkedés
10
Functional interface @FunctionalInterface public interface Operator { public int process(int a, int b); }
11
Lambda kifejezések Operator add = new Operator() { @Override public int process(int a, int b) { return a + b; } }; Operator add = (int a, int b) -> { return a + b;}; Operator add = (a, b) -> { return a + b;}; Operator add = (a, b) -> a + b; UnaryOperator neg = (n) -> -1 * n; UnaryOperator neg = n -> -1 * n;
12
Lambda vs. MethodReference @FunctionalInterface private interface Parser { public int parse(String value); }
• Functional interace = lambda expression Parser p1 = (str) -> {/*return with the int representation*/ };
Metódus referenicák • Metódusra való hivatkozás a meghívása nélkül • Konstruktorra is lehetséges • Szintaxis: "::" (két kettőspont) String::valueOf
x-> String.valueOf(x)
Object::toString
x -> x.toString()
x::toString
() -> x.toString()
HashMap::new
()
-> new HashMap()
14
Mi van a felszín alatt • Referencia oldalon egy Functional interface • Bytecode oldalon Invokedynamics használata • invokevirtual, invokeinterface, invokestatic, invokespecial – invokedynamics • Előre definiált kód eldönti, hogy milyen hívásra van szükség
• Optilmális esetben hatékonyabb mint az Annonymous Inner Class • A JVM fejlődésével az algoritmus még jobb lehet.
15
Lambda és Stream példák private static class Student { private int age; private Gender gender; … } enum Gender { BOY, GIRL; }
16
Stream API nélkül int boysSum = 0; int boysCount = 0; for (Student student : students) { if (student.getGender() == Gender.BOY) { boysSum += student.getAge(); boysCount++; } } double avg = (double) boysSum / boysCount; System.out.println(avg);
Hol készül a Stream? • minden Collection: .stream(), .paralellStream() • primitív array: Arrays.stream(Object[]); • Stream osztályokból: • Stream.of(Object[]), • IntStream.range(int, int) • Stream.iterate(Object, UnaryOperator);
• • • •
BufferedReader.lines(); Files: stream az elérhető file nevekből egy adott könyvtárban Vélentlen számok streamje: Random.ints(); Egyéb helyeken is: BitSet.stream(), Pattern.splitAsStream(java.lang.CharSequence), JarFile.stream(). • Saját implementáció: Spliterator
22
Default metódusok • Könnyebb API fejlődést tesz lehetővé (az interfész később is bővíthető default metódusokkal) • "default" kulcsszó • Method body az interfészben • Felülírható a method body
23
Default metódusok public interface Processor { public void start();
} public class RemoteDataProcessor implements Processor { @Override public void start() {...} }
24
Default metódusok public interface Processor { public void start(); public void init(); } public class RemoteDataProcessor implements Processor { @Override public void start() {} } •
COMPILATION ERROR
25
Default metódusok public interface Processor { public void start(); public default void init() { System.out.println("Processor.init"); } } public class RemoteDataProcessor implements Processor { @Override public void start() {} }
26
Java SE 8 • Apróbb nyelvi finomítások • • • •
Dupla annotációk Paraméter név reflection API-ban Permgen megszüntetése Kompakt profilok
• Új APIk, implementációk, eszközök • Nashorn JS motor • Time API