Java Lambda výrazy: Čo sú a ako ich používať?

Mnohí Java programátori, sa s lambda výrazmi už stretli. Táto funkcionalita bola pridaná už vo verzii Java 8 z roku 2014, takže v súčasnosti už nejde o žiadnu novinku. Je často využívaná programátormi a má množstvo výhod. Ak ti však  lambda výrazy robia problémy alebo nevieš, čo predstavujú, si na správnom mieste.

ambda výrazy v Java
Máš problém s lambda výrazmi v Jave? Poradíme ti, ako ich používať pri programovaní.

V článku sa dozvieš:

    Čo je lambda výraz (expression)?

    Lambda výraz predstavuje funkcionalitu, ktorá bola pridaná ešte v Jave 8. Ide o krátky blok kódu podobný metóde, ale na rozdiel od nej nepotrebuje jej názov metódy a môže byť implementovaný rovno v tele metódy.

    Lambda má niekoľko výhod, a to napríklad, že:

    • sprehľadňuje kód a poskytuje lepšiu čitateľnosť – namiesto niekoľkoriadkového kódu stačí napísať len zopár riadkov,
    • povoľuje použiť funkcionálne programovanie – znamená to použiť funkciu ako vstupný parameter inej funkcie,
    • zlepšuje proces paralelizovania kódu – inak povedané, efektívnejšie vykonávanie kódu na viacjadrových procesoch.

    Syntax lambda výrazu

    Každý lambda výraz musí mať správnu syntax. Len v takom prípade bude mať želaný efekt. Lambda musí obsahovať:

    • zoznam argumentov,
    • znak šípky,
    • telo výrazu.

    V praxi to môže vyzerať takto:

    (zoznam argumentov) -> telo výrazu

    (zoznam argumentov) -> {výraz1; výraz2, …}

     Zoznam argumentov môže byť aj prázdny, napríklad:

    () -> { System.out.println(„Ahoj“); }

     Telo výrazu musí obsahovať zložené zátvorky iba v prípade, ak obsahuje viac ako jeden riadok kódu. V spomenutom príklade ho môžeme vynechať:

    () -> System.out.println(„Ahoj“);

     Typy argumentov môžu a nemusia byť definované, čo znamená, že tieto dva výrazy sú ekvivalentné:

    (x) -> System.out.println(x);

    (Int x) -> System.out.println(x);

     Lambda vie tiež navracať hodnoty, a to bez použitia slova return. Kompilátor si ho vie sám odvodiť:

    (x, y) -> x + y

    Vieš, že…

    … Ak má lambda len jeden parameter, zátvorky nie sú povinné? Kód má teda podobu: x -> System.out.println(x);.

    Príklady použitia lambda

    Pre lepšiu predstavu prinášame tri príklady, ako sa dá lambda výraz použiť.

    Príklad č. 1: Lambda výraz vo forEach

    Lambda výrazy sa často používajú ako parameter funkcie.

    package com.test;
    
    import java.util.ArrayList;
    
    public class LambdaExample1 {
    
    	public static void main(String[] args) {
    		ArrayList<Integer> numbers = new ArrayList<Integer>();
    		numbers.add(1);
    		numbers.add(2);
    		numbers.add(3);
    		// Vytlaci na konzolu 1 2 3 pod sebou. 
    		numbers.forEach(x -> System.out.println(x));
    	}
    }

    Lambda výraz sa dá uložiť do premennej. Platí tu však, že iba vtedy, keď je premenná interface s jednou metódou. V takýchto prípadoch musí mať lambda výraz rovnaký počet parametrov a návratový typ ako daná metóda.

    Java má mnoho používateľských rozhraní. Jedným je napríklad interface Consumer, ktorý využívajú zoznamy:

    java.util.function.Consumer<Integer> function = x -> System.out.println(x);
    numbers.forEach(function);

    Príklad č. 2: Definovanie funkčného interface pre lambda výraz

    Druhý príklad zobrazuje vytvorenie funkčného interface pre základné matematické operácie. Do neho môžeš vkladať výrazy pre sčítanie, odčítanie, násobenie, delenie a metódu operate. Jej úlohou je vziať dve čísla a priradený lambda výraz vypočíta výsledok, ktorý vyzerá nasledovne:

    4 + 2 = 6 
    4 - 2 = 2
    4 * 2 = 8
    4 / 2 = 2

    Vďaka metóde operate priradený lambda výraz rýchlo a jednoducho vypočíta výsledok.

    Do funkčného interface pre základné matematické operácie môžeš vkladať lambda výrazy.

    package com.test;
    
    import java.lang. ArithmeticException;
    
    public class LambdaExample2 {
        // Deklarovanie interfejsu pre lamda vyraz
        interface MathOperation {
            int operation(int x, int y);
        }
        // Deklarovanie metody pre matematicku operaciu
        private int operate (int x, int y, MathOperation mathOperation) {
            return mathOperation.operation (x, y);
        }
        // Vypis celej operacie do konzoly.
        public static void printResult(int x, char c, int y, int z) {
            System.out.printf("%d %s %d = %d\n", x, c, y, z);
        }
        public static void main(String[] args) {
            // Bez deklaracie typu
            MathOperation addition = (x, y) -> x + y;
            // S deklaraciou typu (int)
            MathOperation substraction = (int x, int y) -> x - y;
            // S klucovym slovom return (musi byt v krutenych zatvorkach)
            MathOperation multiplication = (x, y) -> { return (x * y); };
            // Viacriadkovy lambda vyraz
            MathOperation division = (x, y) -> {
                if(y != 0)
                    return (x / y);
                else
                    throw new ArithmeticException("You shouldn't divide a number by zero!");
            };
    
            LambdaExample2 test = new LambdaExample2();
            int a = 4; int b = 2;
            // Scitanie dvoch cisiel
            printResult(a, '+', b, test.operate (a, b, addition));
            // Odcitanie dvoch cisiel
            printResult(a, '-', b, test.operate (a, b, substraction));
            // Vynasobenie dvoch cisiel
            printResult(a, '*', b, test.operate (a, b, multiplication));
            // Vydelenie dvoch cisiel
            printResult(a, '/', b, test.operate (a, b, division));
        }
    }

    Príklad č. 3: Sortovanie, filtrovanie a iterovanie kolekcií cez lambda výrazy

    Výhodou lambda výrazov je, že znižujú potrebu písania vlastných pomocných metód. Zároveň tiež skracujú a sprehľadňujú kód, čím uľahčujú celú prácu. Sila lambda vyniká najmä pri kombinovaní s inou Java funkcionalitou, napríklad kolekciami.

    V nasledujúcom príklade si ukážeme, ako jednoducho triediť, filtrovať a iterovať objekty v kolekcii pomocou lambda výrazov a Java Stream API:

    package com.test;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.stream.Stream;
    
    class Product {
        String name;
        double price;
    
        public Product(String name, double price) {
            this.name = name;
            this.price = price;
        }
    }
    
    public class LambdaExample3 {
    
        public static Product createProduct(String name, double price) {
            return new Product(name, price);
        }
    
        public static void main(String[] args) {
            List<Product> products = new ArrayList();
            products.add(createProduct("Chlieb", 1.0));
            products.add(createProduct("Mlieko", 0.5));
            products.add(createProduct("Keksy", 0.8));
            products.add(createProduct("Smotana", 0.4));
            products.add(createProduct ("Cokolada", 0.7));
    
            // Sortovanie nazvov produktov podla abecedy cez lambdu
            products.sort((p1, p2) -> p1.name.compareTo(p2.name));
    
            // Vyfiltrovanie produktov s cenou (0.5. 1.0)
            Stream<Product> filteredProducts = products.stream().filter(p -> p.price > 0.5 && p.price < 1.0);
    
            // Iterovanie v kolekcii
            filteredProducts.forEach(product -> System.out.println(product.name + ": " + product.price));
        }
    }

    Výstup, ktorý získaš, vyzerá takto:

    Cokolada: 0.7
    Keksy: 0.8

    Lambda výrazy uľahčujú a urýchľujú prácu

    Lambda výrazy sú skvelou funkcionalitou v programovacom jazyku Java. Ich používaním sa dá uľahčiť a urýchliť celá práca. Navyše sprehľadňujú kód a otvárajú nové možnosti. Lambda je súčasťou Java od verzie Java 8. Ak teda používaš staršiu verziu, oplatí sa popremýšľať nad jej aktualizáciou. Pozor si daj na checked výnimky: štandardné funkčné rozhrania ich nedovoľujú vyhodiť, preto ich musíš ošetriť priamo v tele lambda výrazu. Ako na to, ukazujeme v článku o spracovaní výnimiek v Jave.

    Pripravili sme pre teba súbory so spomínanými príkladmi Java Lambda, ktoré si môžeš spustiť priamo v Jave. Stiahni si kód tu.

    O autorovi

    Jozef Wagner

    Java Developer Senior

    Viac ako 10 rokov programujem v Jave, momentálne pracujem v msg life Slovakia ako Java programátor senior a pomáham zákazníkom implementovať ich požiadavky do poistného softvéru Life Factory. Vo voľnom čase si rád oddýchnem v lese, prípadne si zahrám nejakú dobrú počítačovú hru.

    Daj nám o sebe vedieť