Funkcionální programování v Javě

Proč to potřebuji?

Funkcionální programování v Javě (lambda výrazy, Stream API) umožňuje psát stručnější a expresivnější kód pro zpracování kolekcí. Je to moderní přístup, který výrazně zjednodušuje běžné operace jako filtrování, transformace a agregace dat.

Teorie

Funkcionální rozhraní = rozhraní s jednou abstraktní metodou, anotace @FunctionalInterface. Lze nahradit lambda výrazem.

Lambda výraz = anonymní funkce: (parametry) -> tělo.

High-order funkce = funkce, která přijímá nebo vrací jinou funkci. Stream API umožňuje řetězové zpracování kolekcí (map, filter, reduce).

Příklady

import java.util.*;
import java.util.function.*;
import java.util.stream.*;

// === Funkcionální rozhraní ===
@FunctionalInterface
interface Prevod {
    double preved(double hodnota);
}

// Lambda výraz
Prevod celsiusNaFahrenheit = c -> c * 9.0 / 5 + 32;
System.out.println(celsiusNaFahrenheit.preved(100)); // 212.0

// === Standardní funkcionální rozhraní ===
Predicate<String> jeDlouhy = s -> s.length() > 5;
Function<String, Integer> delka = String::length;  // reference na metodu
Consumer<String> vypis = System.out::println;
Supplier<List<String>> novyList = ArrayList::new;

// === Stream API – map, filter, reduce ===
List<String> jmena = List.of("Jan", "Eva", "Kateřina", "Petr", "Alexandra");

// Filter + map + collect
List<String> dlouhaJmena = jmena.stream()
    .filter(j -> j.length() > 3)          // filter: ponechá jen splňující
    .map(String::toUpperCase)              // map: transformace každého prvku
    .sorted()                              // seřazení
    .collect(Collectors.toList());         // sbírání do seznamu
// ["ALEXANDRA", "KATEŘINA", "PETR"]

// Reduce – sčítání
List<Integer> cisla = List.of(1, 2, 3, 4, 5);
int soucet = cisla.stream()
    .reduce(0, Integer::sum);  // 15

// Statistiky
IntSummaryStatistics stats = cisla.stream()
    .mapToInt(Integer::intValue)
    .summaryStatistics();
System.out.println("Průměr: " + stats.getAverage()); // 3.0
System.out.println("Max: " + stats.getMax());         // 5

// Seskupení (groupingBy)
Map<Integer, List<String>> podleDelky = jmena.stream()
    .collect(Collectors.groupingBy(String::length));
// {3=[Jan, Eva], 4=[Petr], 8=[Kateřina], 9=[Alexandra]}

// High-order funkce – metoda přijímající funkci
public static <T> List<T> filtruj(List<T> seznam, Predicate<T> podminka) {
    return seznam.stream()
        .filter(podminka)
        .collect(Collectors.toList());
}
List<String> kratka = filtruj(jmena, j -> j.length() <= 3);
// ["Jan", "Eva"]

Shrnutí

Klíčové body

  • Lambda: (param) -> výraz, reference na metodu: Třída::metoda
  • Funkcionální rozhraní: Predicate, Function, Consumer, Supplier
  • Stream: filter(), map(), reduce(), collect()
  • Stream je lazy – operace se provedou až při terminální operaci (collect, reduce, forEach)