Java 8: Mary Had a Little Lambda http://www.takipiblog.com/2014/04/09/15-must-read-java-8-tutorials/ http://winterbe.com/posts/2014/03/16/java-8-tutorial/ ! http://winterbe.com/posts/2014/07/31/java8-stream-tutorial-examples/ http://www.dreamsyssoft.com/java-8-lambda-tutorial/intro-tutorial.php ? http://blog.hartveld.com/2013/03/jdk-8-33-stream-api.html krit. poznamky http://blog.informatech.cr/2013/03/15/java-lambda-expressions-vs-method-references/ jo http://java.amitph.com/2012/08/at-first-sight-with-closures-in-java.html jojo http://java.amitph.com/2014/02/java-8-streams-api-intermediate.html#.VAbfA6OFlkQ http://www.javaworld.com/article/2092260/java-se/java-programming-with-lambda-expressions.html http://howtodoinjava.com/2014/04/13/java-8-tutorial-streams-by-examples/ http://zeroturnaround.com/rebellabs/java-8-revealed-lambdas-default-methods-and-bulk-data-operations/4/ PJV25
Java 8: “Mary Had a Little Lambda” http://download.java.net/jdk8/docs/api/ std http://docs.oracle.com/javase/tutorial/java/TOC.html std tutorial http://docs.oracle.com/javase/tutorial/collections/streams/index.html http://blog.informatech.cr/2013/03/12/getting-rid-of-boilerplate-code-with-java-lambda-expressions/ slabe Zavádí prvky funkcionálního programování. Zvyšuje se expresivní síla jazyka, ale API ji omezují. Nově zavedené util.streamy představují agregované operace a podporují paralelismus - tedy efektivnější zpracování. Využívají interní iterace, jimiž lze rozdělit data více vláknům vykonávaných případně více procesory. K ovládání operací se využívají LE jako argumenty metod. Interní iterace umožňují reordering, zkrat, paralelismus a lenost. Inversion of control: Hollywood principle: " Don't call us, we'll call you " . PJV25
Java 8 / nové kousky java.time .chrono .format .temporal .zone java.util.function: obsahuje pouze funkcionální interfejsy Bi+, Int+, Double+, Long+ Consumer, Function, Predicate, Supplier, UnaryOperator, BinaryOperator java.util.stream: Collector, BaseStream<…>, Stream<T>, CloseableStream ?? ( Int | Long | Double )Stream, Collectors, StreamSupport , DelegatingStreams ?? java.util: PrimitiveIterator, Spliterator Base64, Spliterators, StringJoiner Optional ( Int | Long | Double | <T> ) ( Int | Long | Double )SummaryStatistics, PJV25
Java 8 / nové triky Efektivně finální je ta proměnná jež se nemění – byť není final. Nové symboly: -> šipka, typová inference ( vnesení, úsudek, vyvození ) :: reference metod a konstruktorů Další užití klíčových slov: default a super Podstatné rozšíření možnosti interfejsu: Jednak o static metody, jednak o default nestatické konkrétní metody. Rozlišují se tzv. SAM ( Single Abstract Method ) interfejsy mající právě jednu abstraktní metodu ( krom generálních ) - tzv. funkcionální interfejs - slouží jako cílový typ pro Lambda Expression a reference metod. Mívá anotaci @FunctionalInterface - což není nutné leč vhodné. Např. tyto interfejsy jsou funkcionální: java.lang.Runnable ( neobohacený ) java.lang.Comparable<T> ( neobohacený ) java.util.Comparator <T> ( značně obohacený ) java.awt.event.ActionListener ( neobohacený ) java.util.function.Consumer <T> ( nový balíček ) PJV25
JSR-335 Closures Closure ( uzávěr ) umožňuje vytvářet reference funkcí a předávat je jako parametry a tedy metody jsou schopné přiložit snímek svého kontextu. PJV25
Lambda výraz ( LE = Lambda Expression ) LE je objekt typu určený funkcionálním interfejsem, zvaný target type, jenž se hledá inferencí z kontextu: na shodu počtu a typů parametrů na kompatibilitu návratového typu na kompatibilitu výrazem vyhazovaných vyjímek LE má >=0 parametrů explicitně deklarovaných či odvozených z kontextu, parametry jsou v závorkách separovány čárkou, pro jediný parametr závorek netřeba. Tělo LE obsahuje >= 0 příkazů ve složených závorkách. Pro jediný příkaz závorek netřeba. Návratový typ anonymní funkce je týž jako tělo výrazu. Při více příkazech je návratový typ anonymní funkce je týž jako typ hodnoty vracené returnem anebo void je-li bez returnu. PJV25
Syntax LE _ > ( ) nulární [ T ] p T – typ explicitně či inferencí ( [ T1 ] p1 [ , [ T2 ] p2, … ] ) p - parametr šipka („arrow token“) e výraz { … ; return e ; } pro metodu-funkci { … ; m( … ) ; [ return; ] } pro void metodu { [ return; ] } prázdné LE jsou realizovány jako anonymní třídy: zmírňují vertikální rozsah zdrojového kódu. lépe vyjadřují this a nedovolují zastiňování proměnných – na rozdil od anonymních tříd. Lokální proměnné referované v LE musejí být [efektivně] final break a continue lze užít jen uvnitř - neovliňují vnější cykly nebo switch _ > PJV25
Příklady inference LE new Thread( ( ) -> { System.out.println( ) ; } ).start( ); // vede k new Thread( new Runnable( ) { public void run( ) { System.out.println( ) ; } } ).start( ); ActionListener al = u -> { long w = u.getWhen( ); [ return; ] }; // vede k: ActionListener al = new ActionListener( ) { public void actionPerformed( ActionEvent u ) { long w = u.getWhen( ); [ return; ] } }; Runnable ActionEvent získáno inferencí PJV25
Příklady inference LE Comparator<Double> coD = ( s1, s2 ) -> s1.compareTo( s2 ); // vede k: Comparator<Double> coD = new Comparator<Double> ( ) { public int compare( Double s1, Double s2 ) { return s1.compareTo( s2 ); } } // Comparator je obohacen o 9 static a 7 default metod Comparator<Float> coF = ( s1, s2 ) -> Float.compare( s1, s2 ); Comparator<Float> coF = new Comparator<Float> ( ) { public int compare( Float s1, Float s2 ) { return Float.compareTo( s1, s2 ); získáno inferencí PJV25
Příklady řazení String[ ] p = { "B", "A", "C" }; Arrays.sort( p, ( Comparators.reversal ); Arrays.sort( p, ( a, b ) -> a.compareTo( b ) ); Arrays.sort( p, String::compareTo ); Arrays.sort( p, Comparators::descending ); Arrays.sort( p, ( new Comparators( ) { } )::normal ); Comparators cs = new Comparators( ) { }; // předchozí případ jinak Comparator<String> c = cs::normal; Arrays.sort( p, c.reversed( ) ); // reversed() viz Comparator kde: interface Comparators { // vlastní příhodný interfejs static Comparator<String> reversal = ( a, b ) -> - a.compareTo(b); static int ascending(String a, String b) { return +a.compareTo(b); } static int descending(String a, String b) { return -a.compareTo(b); } default int normal(String a, String b) { return a.compareTo(b); } } PJV25
Reference metod Symbol :: referuje metodu [ne]statickou anebo konstruktor takto: [ Typ id = ] ( Typ | objekt ~ this | ) :: jménoMetody jménoKonstruktoru [ [ ] ] :: new Příklad: interface Converter<T,R> { public R convert( T t ); static final Converter<Integer, Integer> CF = C -> 9 * C / 5 + 32; // Celsius -> Fahrenheit static final Converter<Number, Double> KMHtoMSEC = v -> v.doubleValue( ) * 1000 / 3600; // km/hod -> m/sec } Converter<String, Integer> S_I = Integer::valueOf; int i = S_I.convert("123"); double f = Converter.CF.convert( 20 ); double v = Converter.KMHtoMSEC.convert( 36 ); PJV25
Reference metod Symbol :: referuje metodu či konstruktor coby argument takto: Typ :: jménoStatickéMetody ( objekt | this ) :: jménoInstančníMetody jménoKonstruktoru [ [ ] … ] :: new PJV25
Reference metod Příklad: String[ ] p = { "Z", "Y", "X" }; Arrays.sort( p, String :: compareTo ); // vede k: Arrays.sort( p, ( string, anotherString )->string.compareTo(anotherString) ); Arrays.sort( p, new Comparator<String>( ) { public int compare( String _this, String anotherString ) { return _this.compareTo( anotherString ); } } ); PJV25
Reference Symbol :: je zástupka za LE, metoda či konstruktor se však tím nevolá. button1.addActionListener( MyFrame::ms ); // ms je void static ( ev -> { MyFrame.m(ev); } ); button2.addActionListener( MyFrame.this::mn ); // mn je void ( ev -> { MyFrame.this.mn(ev); } ); // při překladu se však dosadí retrurn byť je ms či mn void PJV25
Default metody Interfejs může definovat default nestatické konkrétní metody. Implementující třídy nemusejí tyto metody překrýt. Rozšiřující interfejs může překrýt abstract metodu default metodou a i opačně. Defaultní metody nejsou přístupné z LE. Při konfliktu dvou defaultních metod …m(…), lze vybrat jednu z nich takto: class Z implements A, B { public … m(…) { return A.super.m(…); } } PJV25
Příklad Řešení kvadratické rovnice pro reálné kořeny. Pro komplexní kořeny vrací NaN. Quad q1 = ( a, b, c ) -> ( -b + sqrt( b*b - 4*a*c ) ) / ( 2*a ); // tak Quad q2 = ( a, b, c ) -> ( -b - Quad.dis( a, b, c ) ) / ( 2*a ); // či tak double x1 = q1.solve( 2.0, 5.0, -3.0 ), x2 = q2.solve( 2.0, 5.0, -3.0 ); kde: @FunctionalInterface interface Quad { public double solve( double a, double b, double c ); public static double dis( double a, double b, double c) { // diskriminant return Math.sqrt( b*b - 4*a*c ); } PJV25
Obohacení java.util v 1.8 Optional SplitIterators OptionalInt Iterator IntConsumer LongConsumer Iterator SplitIterator <E> <T> LongSummary Statistics SplitIterators OptionalInt PrimitiveIterator <T> IntSummary Statistics DoubleConsumer DoubleSummary Statistics Base64 Int alter Long Double PJV25