Základy programovaní 4 (Java) Stream API Petr Krajča Katedra informatiky Univerzita Palackého v Olomouci Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 1 / 10
Stream API Java 8 nový přístup k práci s kolekcemi nejsou to kolekce jako takové (pouze obalují data) kořeny ve funkcionálním programování ĺıné vyhodnocování podpora implicitně paralelního zpracování svým způsobem DSL (postavený na konceptu fluent interface) Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 2 / 10
Lambda výrazy Lambdas are relegated to relative obscurity until Java makes them popular by not having them. -- James Iry, A Brief, Incomplete, and Mostly Wrong History of Programming Languages funkcionální rozhraní = rozhraní deklarující jednu abstraktní metodu public interface Procedure { public void invoke(object arg); Procedure p = new Procedure() { public void invoke(object arg) { System.out.println("hello " + arg); ; Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 3 / 10
Lambda výrazy z pohledu programátora jsou lambda výrazy syntaktický cukr (argumenty) -> vyraz (Typ1 arg1, Typ2 arg2,...) -> vyraz Procedure p = (Object arg) -> System.out.println(arg); Procedure p = (arg) -> System.out.println(arg); Procedure p = arg -> System.out.println(arg); Procedure p = arg -> { System.out.println(arg); // pokud se ma vratiti hodnota: return "XXX"; Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 4 / 10
Lambda výrazy lze použít i odkazy na metody, operátor :: Trida::statickaMetoda Trida::metoda objekt::metoda Trida::new (konstruktor) class Foo { public static void main(string[] args) { Procedure p = Foo::bar; p.invoke("123"); public static void bar(object arg) { System.out.println(arg); Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 5 / 10
Předchystané funkcionální rozhraní baĺıček java.util.function Supplier<T> metoda T get() Consumer<T> metoda void accept(t t) Predicate<T> metoda boolean test(t t) Function<T, R> metoda R apply(t t) BiFunction<T, U, R> metoda R apply(t t, U u) BiOperator<T,> metoda T apply(t t1, T T2)... Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 6 / 10
Problém s null v kolekcích Map<String, String> foo = new HashMap<>(); foo.put("a", null); foo.get("a"); // ==> null foo.containskey("a"); // ==> true Nová třída Optional<T> obalující výsledky. Optional<T> o =... o.ispresent() // predikat o.ispresent(consumer<t> c) // provedeni consumeru o.orelse(t t) // nahradni hodnota o.orelseget(supplier<t> s) // ziska hodnotu odjinud Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 7 / 10
Stream API Vytvoření streamu z hodnot: Stream.of(1, 2, 3) z pole: Stream.of(fooArray) z kolekce: foo.stream() z jiného streamu: stream.map, stream.filter,... Operace se streamy (1/2) stream.count() vrací počet hodnot stream.filter(predicate p) ponechá ve streamu pouze hodnoty splňující daný predikát stream.distinct() odstraní duplicity (equals) stream.map(function f) aplikuje funkci na každou hodnotu stream.foreach(consumer c) s každým prvkem provede danou operaci stream.sorted(), stream.sorted(comparator c) setřídí stream Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 8 / 10
Stream API Operace se streamy (2/2) stream.findfirst() vrací první prvek streamu (hodnota je typu Optional) stream.findany() vrací jakýkoliv prvek streamu (opět hodnota typu Optional) stream.allmatches(predicate p) vrací true, pokud všechny hodnoty odpovídají predikátu stream.anymatch(predicate p) vrací true, pokud alespoň jedna hodnota odpovídá predikátu stream.nonematch(predicate p) vrací true, pokud ani jedna hodnota neodpovídá predikátu stream.max(comparator c) nejmenší hodnota ve streamu stream.min(comparator c) největší hodnota ve streamu stream.limit(int n) omezí délku streamu na n prvků stream.skip(int n) přeskočí prvních n prvků Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 9 / 10
Stream API Konverze streamu na hodnoty metoda stream.collect(...) hotové řešení ve tříde java.util.stream.collectors Stream.of(employees).map(Employee::getName).iterator(); Stream.of(employees).map(Employee::getName).collect(Collectors.toList()); Stream.of(employees).map(Employee::getName).collect(Collectors.toSet()); Stream.of(employees).map(Employee::getName).collect(Collectors.joining(",")); Stream.of(employees).collect(Collectors.groupingBy(Employee::getDept))); Stream.of(employees).map(Employee::getName).toArray(String[]::new); Paralelizace stream.parallel() vrací paralelní stream; další operace (např. map, foreach mohou být prováděny souběžně) Petr Krajča (UP) KMI/ZP4JV 5. listopad, 2014 10 / 10