Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Java 8 New Features

Java 8 New Features

Focuses on Java 8 new features. Also recap of some Java 7 features are covered.

Jussi Pohjolainen

August 20, 2015
Tweet

More Decks by Jussi Pohjolainen

Other Decks in Technology

Transcript

  1. Java  8  – New  Features  -­‐ Agenda • Word  about

     Certification • Recap  of  some  Java  7  Features • Java  8  Overview – Lambda  Expressions • Method  References • Default  Methods – Optionals – Stream  API – Date  and  Time  API
  2. Oracle  Certified  Associate  (OCP),  Java   SE  7  Programmer •

    70  multiple  choice  questions,  120  minutes,   passing  score  63% • Example  questions:   http://bit.ly/1Lkw6Ao
  3. Oracle  Certified  Professional  (OCP),   Java  SE  7  Programmer •

    Must  pass  OCA  first • 90  multiple  choice  questions,  150  minutes,   passing  score  65% • Example  topics  like  class  design,  generics,   collections,  I/O,  NIO.2,  JDBC,  Threads,   Localization  etc. • Upgrade  exam  available  if  you  have  previous   Java  certificate
  4. Overview • Java  7  was  an  evolutionary update • In

     overall – 1)  Small  language  changes  (Project  Coin) • JSR  334:  Small  language  changes  (Project  Coin) – 2)  Updates  to  File  API   • JSR  203:  New  file  I/O  library – 3)  Updates  to  virtual  machine,  invokedynamic – 4)  Lot  of  smaller  updates • Unicode  6.0,  JDBC  autocloseable,  Java  2D  and  Swing   updates,  xml  stack  update...
  5. Project  Coin • Adds  small  language  changes  to  Java  SE

     7 1. Strings  in  switch 2. Binary  integral  literals  and  underscores  in   numeric  literals 3. Improved  Type  Inference  for  Generic  Instance   Creation 4. Multi-­‐catch   5. try-­‐with-­‐resources  statement
  6. Example class  StringsInSwitch  { public  static  void  main(String  []  args)

     { String  language  =  "Java"; switch(language)  { case  "Java": System.out.println("Hello  from  Java!"); break; case  "PHP": System.out.println("Hello  from  PHP!"); break; default: System.out.println("Not  Java  or  PHP"); } } }
  7. 2.  Binary  integral  literals  and   underscores  in  numeric  literals

    class  BinaryLiterals  { public  static  void  main(String  []  args)  { long  billion  =  1_000_000_000; int  one            =  0b0000_0001; System.out.println(billion); System.out.println(one); } }
  8. 3.  Multi-­‐catch class  MultiCatch   { public  static  void  main(String

      []  args)  { try  { int  number1  =  Integer.parseInt(args[0]); int  number2  =  Integer.parseInt(args[1]); int  result  =  number1  /  number2; System.out.println(result); }  catch(NumberFormatException   |   ArrayIndexOutOfBoundsException   | ArithmeticException   e)  { e.printStackTrace(); } } }
  9. 4.  Type  Inference • No  need  to  repeat  the  generic

     typing   (diamond) List<String>  list  =  new  ArrayList<>(); Map<String,  String>  map  =  new   HashMap<>();
  10. We  have  a  problem... try  { BufferedReader  inputStream  =  

    new  BufferedReader(new   FileReader("input.txt")); System.out.println(  inputStream.readLine()  ); inputStream.close(); }  catch(  IOException  e)  { e.printStackTrace(); }
  11. Recommend  (and  complicated)  way  to  do  close() BufferedReader   inputStream

     =  null; try  { inputStream   =  new  BufferedReader(new   FileReader("output.txt")); System.out.println(   inputStream.readLine()   ); }  catch(  IOException   e)  { e.printStackTrace(); }  finally  { try  { if  (inputStream   !=  null)  { inputStream.close(); } }  catch(IOException   e)  { e.printStackTrace(); } }
  12. Auto  close to  the  rescue! try  (BufferedReader  inputStream  =  

    new  BufferedReader(new  FileReader("output.txt")))  { System.out.println(  inputStream.readLine()  ); }  catch(  IOException  e)  { e.printStackTrace(); }
  13. How? • Virtual  Machine  will  call  automatically  the   close

    method  upon  exiting  the  try  block  (like   finally) • The  resource  object  must  implement   AutoCloseable interface • The  interface  has  only  one  method:  close • If  closing  causes  exception,  it’s  suppressed   (ignore).  Possible  to  get  it  using   getSuppressed() method
  14. API  Updates  to  File  System • java.io and  java.nio are

     updated • Called  NIO.2  revision • New  classes  (java.nio): – Path – Locate  a  file  in  a  file  system • Paths  – Convert  a  URI  to  Path  object – Files – Operate  on  files,  directories  and  other   types  of  files – FileVisitor – Traversing  files  in  a  tree   – WatchService – File  change  modification  API
  15. Path  and  Files  Example import  java.nio.charset.Charset; import  java.nio.file.*; import  java.io.*;

    import  java.util.List; class  Main  { public  static  void  main(String  []  args)  throws  IOException  { //  Moving  file Path  src      =  Paths.get("./FilesExample.java"); Path  dest    =  Paths.get("./dir/FilesExample.java"); Files.move(src,  dest,  StandardCopyOption.REPLACE_EXISTING); //  Reading  file Path  myPath  =  new  File("./dir/FilesExample.java").toPath(); List<String>  lines  =  Files.readAllLines(myPath,  Charset.defaultCharset()); for(String  line  :  lines)  { System.out.println(line); } } }
  16. java.nio.file.FileVisitor • Recursively  visit  files  in  a  file  tree –

    Example:  delete  every  .class  file  in  a  tree • Implement  a  class  that  implements  FileVisitor interface – preVisitDirectory – postVisitDirectory – visitFile – visitFileFailed • Or  extend  SimpleFileVisitorthat  has  default   behaviour for  each  of  these  methods!
  17. java.nio.file.WatchService • Monitor  directory for  changes • Example:  text  editor

     notifies  if  someone  else   has  made  changes  to  your  document   – (“The  following  files  were  changes  by  another  program”) • Watch  Service  API  enables  you  to  register  a   directory  with  the  watch  service • When  registering  tell  are  you  interested  in  file   creation,  file  deletion  or  file  modification!
  18. Overview • Java  8  Programming  Language – Lambdas,  Method  references,

     Default  methods • Collections:  Stream  API • Optionals • Date  – Time  Package
  19. Biggest  Changes  in  Language • Lambda  Expressions • Method  References

    • Default  and  Static  methods  in  interfaces
  20. Inner  Classes • Before  introducing  the  concept  of  Lambdas,  

    let's  first  focus  on  the  problem  it  tries  to   solve. • Java  has  the  concept  of  inner  classes  that   might  be  problematic – class  Outer  {  class  Inner  {}  }
  21. Java  1.1:  "listener"  interfaces class  Main  extends  JFrame { public

     Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new  Listener(this)); setSize(300,300); setVisible(true); } public  static  void  main(String  []  args)  { new  Main("Title"); } } class   Listener   implements   ActionListener   { private   Main   main; public   Listener(Main   main)   { this.main   =  main; } @Override public   void   actionPerformed(ActionEvent   e)  { main.setTitle("Click!"); } }
  22. Easy  Access:  Inner  Classes import  javax.swing.*; import  java.awt.event.ActionEvent; import  java.awt.event.ActionListener;

    class  Main  extends  JFrame  { public  Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new  Listener()); setSize(300,300); setVisible(true); } class  Listener  implements  ActionListener  { @Override public  void  actionPerformed(ActionEvent   e)  { setTitle("Click!"); } } public  static  void  main(String  []  args)  { new  Main("Title"); } }
  23. Easy  Access:  Inner  Classes  in  Methods class  Main  extends  JFrame

     { public  Main(String  title)  { super(title); class  Listener  implements  ActionListener  { @Override public  void  actionPerformed(ActionEvent   e)  { setTitle("Click!"); } } JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new  Listener()); setSize(300,300); setVisible(true); } public  static  void  main(String  []  args)  { new  Main("Title"); } }
  24. Example:  Event  Handling class   Main   extends   JFrame

      { public   Main(String   title)   { super(title); JButton   click   =  new   JButton("Click"); add(click); click.addActionListener(new   ActionListener()   { @Override public   void   actionPerformed(ActionEvent   e)   { setTitle("Click!"); } }); setSize(300,300); setVisible(true); } public   static   void   main(String   []  args)   { new   Main("Title"); } }
  25. Lambdas • Key  feature  Lambda  Expressions  for  handling   "blocks"

     of  code • Referred  also  as  closures or  anonymous   methods • Lambdas  are  a  short  way  of  creating  a   methods  which  will  be  invoked  later  on
  26. Lambda  to  the  Rescue! class  Main  extends  JFrame  { public

     Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener((ActionEvent   e)  -­‐>  { setTitle("Click!"); }); setSize(300,   300); setVisible(true); } public  static  void  main(String  []  args)  { new  Main("Title"); } }
  27. class  Main  { public  static  void  main(String   []  args)

     { Runnable   r1  =  new  Runnable()   { public  void  run()  { System.out.println("Hello!"); } }; new  Thread(r1).start(); //  Same  than class  Anonymous   implements   Runnable   { public  void  run()  { System.out.println("Hello!"); } } Runnable   r2  =  new  Anonymous(); new  Thread(r2).start(); //  Does  the  same  but  is  NOT  the  same Runnable   r3  =  ()  -­‐>  System.out.println("Hello!"); new  Thread(r3).start(); } } Lambda  is   not  an  inner  class!
  28. Functional  Interface • Functional  interface  is  an  interface  with  one

      method • To  declare  an  functional  interface,  use  annotation   @FunctionalInterface – No  ambiguity  of  which  method  should  the  lambda   define  in  the  interface! • You  will  get  compiler  error  if  you  have  the annotation  and  several  methods  in  interface • If  interface  has  only  one  method,  it's  functional.
  29. class   Main   { public   static   void

      main(String   []  args)   { method1(()   -­‐>   System.out.println("Hello")); method2(()   -­‐>   System.out.println("Hello")); //  method3(()   -­‐>   System.out.println("Hello"));   -­‐>   does   not   work } public   static   void   method1(SomeInterface1   someInterface1)   { someInterface1.doSomething(); } public   static   void   method2(SomeInterface2   someInterface2)   { someInterface2.someOtherMethod(); } public   static   void   method3(SomeInterface3   someInterface3)   { someInterface3.a(); someInterface3.b(); } } @FunctionalInterface interface   SomeInterface1   { public   void   doSomething(); //   public   void   youCannotAddAnotherMethodHere(); } interface   SomeInterface2   { public   void   someOtherMethod(); } interface   SomeInterface3   { public   void   a(); public   void   b(); }
  30. Lambda  Syntax • Three  parts 1. Parenthesized  set  of  parameters:

     () 2. Arrow:  -­‐> 3. Body:  can  be  single  expression  or  a  block:  {}
  31. Example class  Main  { public  static  void  main(String   []

     args)  { String  []  data  =  {"a",  "bb",  "b",  "kkk",  "jjjj"}; Comparator<String>   comparator   = (String  a,  String  b)  -­‐> { return  a.length()   -­‐ b.length(); }; Arrays.sort(data,   comparator); System.out.println(Arrays.toString(data)); } }
  32. Type  Inference class  Main  { public  static  void  main(String  

    []  args)  { String  []  data  =  {"a",  "bb",  "b",  "kkk",  "jjjj"}; Comparator<String>   comparator   = (a,  b)  -­‐> { return  a.length()   -­‐ b.length(); }; Arrays.sort(data,   comparator); System.out.println(Arrays.toString(data)); } } If  target  type  is   Comparator<String>,   then  arguments  must  be   String!  No  need  to  declare   these!
  33. Type  Inference class  Main  { public  static  void  main(String  

    []  args)  { String  []  data  =  {"a",  "bb",  "b",  "kkk",  "jjjj"}; Arrays.sort(data,   (a,  b)  -­‐> { return  a.length()   -­‐ b.length(); }); System.out.println(Arrays.toString(data)); } } If  data  is  String[] then  it  must  be  passed   Comparator<String>  
  34. Single  Expression class  Main  { public  static  void  main(String  

    []  args)  { String  []  data  =  {"a",  "bb",  "b",  "kkk",  "jjjj"}; Arrays.sort(data,   (a,  b)  -­‐>  a.length()   -­‐ b.length()); System.out.println(Arrays.toString(data)); } } If  you  use  single   expression,  Java  runtime   evaluates  the  expression   and  returns  a  value!
  35. Notice  any  problems? class  Main  extends  JFrame  { private  ActionEvent

     actionEvent; public  Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new   ActionListener()   { @Override public  void  actionPerformed(ActionEvent   actionEvent)   { this.actionEvent   =  actionEvent; } }); setSize(300,   300); setVisible(true); } public  static  void  main(String[]   args)  { new  Main("Title"); } }
  36. Notice  any  problems? class  Main  extends  JFrame  { private  ActionEvent

     actionEvent; public  Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new   ActionListener()   { @Override public  void  actionPerformed(ActionEvent   actionEvent)   { this.actionEvent   =  actionEvent; } }); setSize(300,   300); setVisible(true); } public  static  void  main(String[]   args)  { new  Main("Title"); } } actionEvent is  not  an   attribute  of  declared   anonymous  class!
  37. Fixed! class  Main  extends  JFrame  { private  ActionEvent  actionEvent; public

     Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener(new   ActionListener()   { @Override public  void  actionPerformed(ActionEvent   actionEvent)   { Main.this.actionEvent   =  actionEvent; } }); setSize(300,   300); setVisible(true); } public  static  void  main(String[]   args)  { new  Main("Title"); } } Proper  way  of  referencing   outer  classes  attribute
  38. Using  Lambdas class  Main  extends  JFrame  { private  ActionEvent  

    actionEvent; public  Main(String  title)  { super(title); JButton  click  =  new  JButton("Click"); add(click); click.addActionListener((actionEvent)   -­‐>  { this.actionEvent   =  actionEvent; }); setSize(300,   300); setVisible(true); } public  static  void  main(String[]   args)  { new  Main("Title"); } } this does  not  reference   to  the  lambda!  This  works!
  39. Does  this  compile? class  Outer  { private  int  x  =

     1; public  void  method()  { int  y  =  2; final  int  z  =  3; class  Inner  { public  void  method()  { System.out.println(x); System.out.println(y); System.out.println(z); } } new  Inner().method(); } } class  Main  { public  static  void  main(String[]  args)  { new  Outer().method(); } }
  40. Rules  using  variables  and  Inner  Classes class  Outer  { private

     int  x  =  1; public  void  method()  { int  y  =  2; final  int  z  =  3; class  Inner  { public  void  method()  { System.out.println(x); System.out.println(y); System.out.println(z); } } new  Inner().method(); } } class  Main  { public  static  void  main(String[]  args)  { new  Outer().method(); } } Java  7:   only  final  variables  allowed. Java  8:   final  and  effectively  final  variables  allowed!
  41. Effectively  Final class  Outer  { private  int  x  =  1;

    public  void  method()  { int  y  =  2;                    //  Effectively  final,  java  8:  YES,  java  7:  NO final  int  z  =  3;        //  Final,                          java  8:  YES,  java  7:  YES int  v  =  1; v  =  2;                            //  Variable,                    java  8:  NO,    java  7:  NO class  Inner  { public  void  method()  { System.out.println(x); System.out.println(y); System.out.println(z); //  System.out.println(v); } } new  Inner().method(); } } class  Main  { public  static  void  main(String[]  args)  { new  Outer().method(); } }
  42. Effectively  Final  and  Lambdas class  Main  { public  static  void

     main(String   []  args)  { String  message   =  "Works"; final  String  MESSAGE  =  "Works"; //  message  =  "DO  NOT  work"; Thread  t  =  new  Thread(  ()  -­‐>  { System.out.println(message); System.out.println(MESSAGE); }  ); t.start(); } }
  43. Method  References • Use  lambda  expressions  to  create  anonymous  

    methods. • If  the  expression  just  calls  an  existing  method,   you  can  refer  to  that  method  by  using  it's   name
  44. Intro  to  Method  Reference class   Person   { private

      String   firstName; private   String   lastName; public   Person(String   firstName,   String   lastName)   { this.firstName   =  firstName; this.lastName   =  lastName; } public   String   getFirstName()   { return   firstName; } public   String   getLastName()   { return   lastName; } @Override public   String   toString()   { return   lastName   +  "  "  +  firstName; } //   Helper   method   for   comparing   persons public   static   int   compareByLastName(Person   a,  Person   b)   { return   a.lastName.compareTo(b.lastName); } }
  45. class   Main   { public   static   void

      main(String   []  args)   { Person   []   array   =  {new   Person("jack",   "smith"), new   Person("tina",   "bauer")}; //  Use   anonymous   inner   class   to   sort   but   use  a  method   already //  defined. Arrays.sort(array,   new   Comparator<Person>()   { @Override public   int   compare(Person   o1,   Person   o2)   { return   Person.compareByLastName(o1,   o2); } } ); //  Use   lambda Arrays.sort(array,   (Person   o1,   Person   o2)   -­‐>  { return   Person.compareByLastName(o1,   o2); } ); //  Since   array   type   is   String,   o1   and   o2  must   be  String //  and   you   don't   have   to   declare   them. Arrays.sort(array,   (o1,   o2)   -­‐>  { return   Person.compareByLastName(o1,   o2); } ); //  By  default   lambda   will   return   the   value   of   a  single   expression Arrays.sort(array,   (o1,   o2)   -­‐>  Person.compareByLastName(o1,   o2)   ); //  Since   we  are   calling   only   one   method   in   lambda,   we  are //  using   a  method   reference! Arrays.sort(array,   Person::compareByLastName   ); System.out.println(Arrays.toString(array)); } } Static  method  reference:   Person.compareByLastName(o1,  o2)
  46. class   Person   { ... public   static  

    int   compareByLastName(Person   a,  Person   b)   { System.out.println("a"); return   a.lastName.compareTo(b.lastName); } public   int   compareByFirstName(Person   a,  Person   b)   { return   a.firstName.compareTo(b.firstName); } public   int   compareByFirstName(Person   b)  { return   this.firstName.compareTo(b.firstName); } } class   Main   { public   static   void   main(String   []  args)   { Person   []   array   =  {new   Person("jack",   "smith"), new   Person("tina",   "bauer")}; //  Static   method   reference //  -­‐>  Person.compareByLastName(o1,   o2) Arrays.sort(array,   Person::compareByLastName   ); //  Object   method   reference //  -­‐>  new   Person().compareByFirstName(o1,   o2) Arrays.sort(array,   new   Person()::compareByFirstName   ); //  Instance   method   of   an  arbitrary   object   of  particular   type //  -­‐>  o1.compareByFirstName(o2) Arrays.sort(array,   Person::compareByFirstName   ); System.out.println(Arrays.toString(array)); } } This  can  mean  both   o1.compareByFirstname(o2)   and Person.compareByFirstname(o1,   o2)!   If  you  have  both  methods  in  class,  you  will  have   a  compiler  error!
  47. import  javax.swing.*; import  java.awt.event.ActionEvent; import  java.awt.event.ActionListener; class  MyWindow  extends  JFrame

     { public  MyWindow()  { JButton  ok  =  new  JButton("Ok"); add(ok); ok.addActionListener(new  ActionListener()  { public  void  actionPerformed(ActionEvent  e)  { System.out.println(e); } }); ok.addActionListener((ActionEvent  e)  -­‐>  {  System.out.println(e);  }); ok.addActionListener((e)  -­‐>  System.out.println(e)  ); //  Object  method  reference! ok.addActionListener(System.out::print); setVisible(true); setSize(300,300); } } class  Main  { public  static  void  main(String  []  args)  { new  MyWindow(); } } Object  Method   Reference
  48. import  javax.swing.*; import  java.awt.event.ActionEvent; import  java.awt.event.ActionListener; class  MyWindow  extends  JFrame

     { public  MyWindow()  { JButton  ok  =  new  JButton("Run!"); add(ok); ok.addActionListener(this::startThread); setVisible(true); setSize(300,300); } public  void  startThread(ActionEvent   e)  { new  Thread(this::startMoving).start(); } public  void  startMoving()  { while(true)  { this.move(this.getX()  +  1,  this.getY()); try  { Thread.sleep(50); }  catch  (InterruptedException   e)  { e.printStackTrace(); } } } } class  Main  { public  static  void  main(String  []  args)  { new  MyWindow(); } } Object  Method   Reference Object  Method   Reference
  49. Default  Methods • Extend  interfaces  without  breaking  any  code –

    Java  7:  if  you  add  another  method  to  interface,   every  class  implementing  that  interface  must   implemented  again • Helps  to  create  utility  classes  where   implementation  is  part  of  the  interface • Can  provide  default  implementation  of   methods  for  classes.  Class  may  override  the   implementation
  50. Basic  Interface class Robot  implements Movable  { public void start()

    { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface Movable  { public void start(); public void stop(); } class MyApp  { public static void main(String [] args) { new Robot().start(); } }
  51. Problem  When  Modifying  the  Interface class Robot  implements Movable  {

    public void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface Movable  { public void start(); public void stop(); public void fly(); } class MyApp  { public static void main(String [] args) { new Robot().start(); } } Now  every  class  that   has  implemented  the   Movable  must  be   changed!
  52. Default  Method class Robot   implements Movable   { public

    void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface Movable   { public void start(); public void stop(); default public void fly() { System.out.println("I'm   flying!"); } } class MyApp   { public static void main(String [] args) { new Robot().fly(); } } No  changes  to  Robot,   suddenly  it  holds  a   new  method  fly.  Robot   can  also  override  this.
  53. Problem? class Robot  implements Movable,  FlyingMachine  { public void start()

    { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface FlyingMachine  { default public void fly() { System.out.println("FlyingMachine:  I'm  flying!"); } } interface Movable  { public void start(); public void stop(); default public void fly() { System.out.println("Movable:  I'm  flying!"); } } class MyApp  { public static void main(String [] args) { new Robot().fly(); } }
  54. class Robot   implements Movable,   FlyingMachine   { public

    void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } @Override public void fly() { FlyingMachine.super.fly(); } } interface FlyingMachine   { default public void fly() { System.out.println("FlyingMachine:   I'm   flying!"); } } interface Movable   { public void start(); public void stop(); default public void fly() { System.out.println("Movable:   I'm   flying!"); } } class MyApp   { public static void main(String [] args) { new Robot().fly(); } } You  must  override  the  method!  To   invoke  default  interface  method,  use   interface.super.method()
  55. It’s  for  Assisting  Default  Methods! class Robot  implements FlyingMachine  {

    public void start() { System.out.println("Starting"); } public void stop() { System.out.println("Stopping"); } } interface FlyingMachine  { default public void fly() { System.out.print("FlyingMachine:   "); assistFlying(); } static void assistFlying() { System.out.println("Fly!"); } } class MyApp  { public static void main(String [] args) { new Robot().fly(); FlyingMachine.assistFlying(); //  Robot.assistFlying();  -­‐>  Does  NOT  work! } }
  56. Does  it  Compile? @FunctionalInterface interface FlyingMachine   { public void

    fallFromSky(); default public void fly() { System.out.print("FlyingMachine:   "); assistFlying(); } static void assistFlying() { System.out.println("Fly!   "); } } class MyApp   { public static void main(String [] args) { someMethod( () -­‐> System.out.println("Falling!") ); } public static void someMethod(FlyingMachine   f) { f.fallFromSky(); f.fly(); } }
  57. Why  can  we  use  Lambda? class  Main  { public  static

     void  main(String   []  args)  { String  []  data  =  {"a",  "bb",  "b",  "kkk",  "jjjj"}; Comparator<String>   comparator   = (a,  b)  -­‐> { return  a.length()   -­‐ b.length(); }; Arrays.sort(data,   comparator); System.out.println(Arrays.toString(data)); } }
  58. Stream  API? • This  is  not  about  java.io!  It’s  all

     about  doing   operations  on  elements! • Stream  API  provides  a  powerful  way  of  do   different  kind  of  operations  on  data – filtering – sorting – ... • Streams  can  be  created  from  collections – stream() and  parallelStream() • Streams  are  all  about  computations,  collections   are  about data
  59. Example class  Main  { public  static  void  main(String[]   args)

     { List<String>   myList  = Arrays.asList("a1",   "a2",  "b1",  "c2",  "c1"); myList.stream() .filter(s   -­‐>  s.startsWith("c")) .map(s  -­‐>  s.toUpperCase()) .sorted() .forEach(s   -­‐>  System.out.println(s)); } }
  60. Background • Stream  is  a  sequence  of  elements  from  a

      source  that  supports  aggregate  operations • Sequence  of  elements  from  a  source – Source  can  be  collection,  array,  I/O – Stream  is  an  interface  to  the  elements • Aggregate  Operations – filter,  map,  reduce,  find,  match,  sorted ...
  61. Pipelining  and  Iteration • Many  stream  operations  (filter,  map  ..)

     returns   a  stream  itself.  Allows  operations  to  be   chained  to  form  a  larger  pipeline • Internal  iteration  happens  behind  the  scenes,   so  developer  does  not  have  iterate  the   collections
  62. Iteration import  java.util.Arrays; import  java.util.List; class  Main  { public  static

     void  main(String[]   args)  { System.out.println("**   Collection   **"); List<String>   list  =  Arrays.asList("a",   "b",  "c",  "d"); for(String   element  :  list)  { System.out.println(element); } System.out.println("**   Stream  **"); list.stream().forEach(s   -­‐>  System.out.println(s)); } }
  63. Breaking  it  Down import  java.util.Arrays; import  java.util.List; import  java.util.stream.Stream; class

     Main  { public  static  void  main(String[]   args)  { List<String>   list  =  Arrays.asList("x",   "e",  "c",  "a"); //  Returns  Stream<T>   Interface Stream<String>   stream  =  list.stream(); //  Returns  Stream<T>   Interface Stream<String>   sortedStream   =  stream.sorted(); sortedStream.forEach(s   -­‐>  System.out.println(s)); } }
  64. import  java.util.Arrays; import  java.util.List; import  java.util.function.Consumer; import  java.util.stream.Stream; class  PrintCollection

     implements  Consumer<String>  { @Override public  void  accept(String  s)  { System.out.println(s); } } class  Main  { public  static  void  main(String[]  args)  { List<String>  list1  =  Arrays.asList("a",  "b",  "c",  "d"); List<String>  list2  =  Arrays.asList("a",  "b",  "c",  "d"); List<String>  list3  =  Arrays.asList("a",  "b",  "c",  "d"); List<String>  list4  =  Arrays.asList("a",  "b",  "c",  "d"); List<String>  list5  =  Arrays.asList("a",  "b",  "c",  "d"); list1.stream().forEach(new  PrintCollection()); list2.stream().forEach(new  Consumer<String>()  { @Override public  void  accept(String  s)  { System.out.println(s); } }); list3.stream().forEach((String  s)  -­‐>  System.out.println(s)); list4.stream().forEach(s  -­‐>  System.out.println(s)); list5.stream().forEach(System.out::println); } }
  65. Different  Streams • It’s  possible  to  create  streams  from  Collections

      and  just  a  bunch  of  objects – Stream.of("a1",  "a2",  "a3").filter(...).forEach(...) • Also  for  primitive  types – IntStream.range(1,  4).filter(...).forEach(...)
  66. Example import  java.util.stream.Stream; class  Main  { public  static  void  main(String[]

      args)  { //  "forEach:  A2" Stream.of("d2",   "a2",  "b1",  "b3",  "c") .map(s  -­‐>  { return  s.toUpperCase(); }) .filter(s  -­‐>  { return  s.startsWith("A"); }) .forEach(s  -­‐>  System.out.println("forEach:   "  +  s)); } }
  67. Collect • Terminal  operation  that  transforms  the   elements  of

     stream  to  a  new  result – List,  Set,  Map • Collect accepts  Collector – Various  built-­‐in  Collectors available  via   Collectors – class • Collectors.toSet(),   Collectors.toList(),   Collectors.toMap()
  68. Example public  static  void  main(String[]   args)  { List<Person>  

    persons  =  null; try  { persons  =  fetchNames(RANDOM_USER_URL); }  catch  (IOException   e)  { e.printStackTrace(); System.exit(0); } List<Person>   filteredPersons   = persons.stream() .filter(person   -­‐>  { return  person.getFirstName().startsWith("a"); }) .collect(Collectors.toList()); System.out.println(filteredPersons); }
  69. Parallel  Streaming • Streams  can  be  executed  in  parallel  to

      increase  performance • Use  parallelStream() instead  of   stream()
  70. Example public  static  void  main(String[]  args)  { ForkJoinPool  commonPool  =

     ForkJoinPool.commonPool(); System.out.println(commonPool.getParallelism());        //  7 List<Person>  persons  =  null; try  { persons  =  fetchNames(RANDOM_USER_URL); }  catch  (IOException  e)  { e.printStackTrace(); System.exit(0); } List<Person>  filteredPersons  = persons.parallelStream() .map(person  -­‐>  { System.out.println("MAP:  "  +  Thread.currentThread().getName()); person.setLastName(person.getLastName().toUpperCase()); person.setFirstName(person.getFirstName().toUpperCase()); return  person; }) .filter(person  -­‐>  { System.out.println("FILTER:  "  +  Thread.currentThread().getName()); return  person.getFirstName().startsWith("A"); }) .collect(Collectors.toList()); System.out.println(filteredPersons); }
  71. Problem  in  Java class StockExchange  { public static String findStockCode(String

    company) { if(company.equals("Nokia")) { return "NOK"; } else if (company.equals("Apple")) { return "AAPL"; } else { return null; } } } class MyApp  { public static void main(String [] args) { String code  = StockExchange.findStockCode(  args[0]  ); System.out.println(  code.toLowerCase()  ); } }
  72. Same  in  Swift class StockExchange  { class func findStockCode(company  :

     String)  -­‐>  String?  { if(company  ==  "Nokia")  { return "NOK"; }  else if (company  ==  "Apple")  { return "AAPL"; }  else { return nil; } } } var code  :  String?  =  StockExchange.findStockCode(  Process.arguments[1]  ); //  Compile  error! //  Its  a  hint  for  the  developer  that  you  must  check  nil  values! println(code.lowercaseString); String?  is  an  optional String.  Can  contain  nil  or   String
  73. Swift:  Linking  multiple  levels  of  chains class Person  { var

    pet:  Pet? } class Pet  { var name:  String var favoriteToy:  Toy? init(name:  String)  { self.name =  name } } class Toy  { var name:  String? init(name:  String)  { self.name =  name } } 92 //  Create  person var jack  =  Person() //  Create  pet var spot  =  Pet(name:  "Spot") //  Create  toy var ball  =  Toy(name:  "Ball") //  Jack  will  have  a  pet  named  Spot  which   favorite //  toy  is  ball spot.favoriteToy =  ball jack.pet =  spot //  Printing  the  name....  Aaargh! if var pet  =  jack.pet { if var toy  =  pet.favoriteToy { if var name  =  toy.name { println(name) } } }
  74. Using  ?  and  ! in  Swift //  Hard  unwrapping,  

    will  crash  if  some  of  these  is //  nil var name1  :  String  =  jack.pet!.favoriteToy!.name! println(name1)    //  "Ball" //  Will  return  always  on  optional  string //  result  is  nil,  if  pet,  favoriteToy  or  name  is  nil var name2  :  String?  =  jack.pet?.favoriteToy?.name println(name2)    //  Optional("Ball") //  If  pet,  favoriteToy  or  name  is  nil,  don't  execute //  the  code.  If  these  are  not  nil,  fetch  the  name //  AND  unwrap  it if var name3  =  jack.pet?.favoriteToy?.name   { println(name3) } 93
  75. Back  to  Java • This  might  crash  if  some  of

     these  return  NULL – String  version  =   computer.getSoundcard().getUSB().getVersion(); • A  lot  nested  checks  (if  not  null)  is  required   here. • Java  8  Introduces  a  new  class  called   java.util.Optional<T> to  handle  this • Single-­‐value  container  that  either  contains  a   value  or  not  (null)
  76. class  Car  { private  Optional<Motor>  motor; public  Car(Motor  motor)  {

    //  motor  may  hold  value  or  null this.motor  =  Optional.ofNullable(motor); } public  Car()  { this.motor  =  Optional.empty(); } public  Optional<Motor>  getMotor()  { return  motor; } public  void  setMotor(Motor  motor)  { this.motor  =  Optional.of(motor); } } class  Motor  { private  int  horsePower; public  Motor(int  horsePower)  { this.horsePower  =  horsePower; } public  int  getHorsePower()  { return  horsePower; } public  void  setHorsePower(int  horsePower)  { this.horsePower  =  horsePower; } } class  Main  { public  static  void  main(String[]  args)  { Car  datsun  =  new  Car(  new  Motor(40)  ); datsun.getMotor().ifPresent(motor   -­‐>  { System.out.println(motor.getHorsePower()); }); Car  skoda  =  new  Car(  null  ); skoda.getMotor().ifPresent(motor   -­‐>  { System.out.println(motor.getHorsePower()); }); Car  peugeot  =  new  Car(); peugeot.getMotor().ifPresent(motor   -­‐>  { System.out.println(motor.getHorsePower()); }); } } Programmer  is  now  forced  to   think  about  what  happens  if  the   result  is  null!
  77. Creating  Optional //  an  empty  'Optional'; Optional<String>   empty  =

     Optional.empty(); //  an  'Optional'   where  you  know  that  it  will  not  contain  null; //  (if  the  parameter   for  'of'  is  null,  a   //  'NullPointerException'   is  thrown) Optional<String>   full  =  Optional.of("Some   String"); //  an  'Optional'   where  you  don't  know  whether   //  it  will  contain  null  or  not Optional<String>   halfFull   =   Optional.ofNullable(someOtherString);
  78. Using  ifPresent class  Main  { public  static  void  main(String[]  args)

     { Car  datsun  =  new  Car(  new  Motor(40)  ); datsun.getMotor().ifPresent(motor  -­‐>  { System.out.println(motor.getHorsePower()); }); } }
  79. class  Human  { Optional<Pet>  pet; public  Human(Pet  p)  { pet

     =  Optional.ofNullable(p); } public  Optional<Pet>   getPet()  { return  pet; } } class  Pet  { private  Optional<Toy>   favoriteToy; private  String  name; public  Pet(Toy  toy,  String  name)  { favoriteToy   =  Optional.ofNullable(toy); this.name  =  name; } public  Optional<Toy>   getToy()  { return  favoriteToy; } public  String  getName()  { return  name; } } class  Toy  { private  String  name; public  Toy(String  name)  { this.name  =  name; } public  String  getName()   { return  name; } }
  80. map class  Main  { public  static  void  main(String[]   args)

     { Toy  ball  =  new  Toy("ball"); Pet  spot  =  new  Pet(ball,   "Spot"); Human  jack  =  new  Human(spot); //  If  getPet  has  a  value,  unwrap  the  optional   from //  getPet  and  invoke  it's  getName()   method // //  if  getPet  has  no  value,  then  return  empty  Optional Optional<String>   name  =  jack.getPet().map(Pet::getName); //  print  the  name  if  jack.getPet()   was  not  null! name.ifPresent(System.out::println); } }
  81. filter class  Main  { public  static  void  main(String[]   args)

     { Toy  ball  =  new  Toy("ball"); Pet  spot  =  new  Pet(ball,  "Spot"); Human  jack  =  new  Human(spot); //  Did  we  manage  to  retrieve  the  name? Optional<String>   maybeName  =  jack.getPet().map(Pet::getName); //  Is  the  name  "Spot"? Optional<String>   maybeSpot  =  maybeName.filter(n   -­‐>  { return  n.equals("Spot"); }); //  If  "Spot"  was  present,  print  it  out maybeSpot.ifPresent(System.out::println); } }
  82. filter class  Main  { public  static  void  main(String[]   args)

     { Toy  ball  =  new  Toy("ball"); Pet  spot  =  new  Pet(ball,  "Spot"); Human  jack  =  new  Human(spot); //  If  jack  has  a  pet  and  it's  name  is  Spot,  print  the  name  to  console jack.getPet().map(p   -­‐>  p.getName()) .filter(name  -­‐>  name.equals("Spot")) .ifPresent(name   -­‐>  System.out.println(name)   ); } }
  83. flatMap class  Main  { public  static  void  main(String[]  args)  {

    Toy  ball  =  new  Toy("ball"); Pet  spot  =  new  Pet(ball,  "Spot"); Human  jack  =  new  Human(spot); Optional<Pet>  maybePet  =  jack.getPet(); //  Notice  that  getName  returns  String,  but  name  here  is //  Optional!  It's  optional  because  maybePet  may  contain  null. Optional<String>  name  =  maybePet.map(pet  -­‐>  pet.getName()); //  Now  the  pet.getToy  return  Optional<Toy>,  so  the  end  result //  is  Optional<Optional<Toy>>!! Optional<Optional<Toy>>  maybeMaybeToy  =  maybePet.map(pet  -­‐>  pet.getToy()); //  Use  flatMap  instead  of  flat! Optional<Toy>  maybeToy  =  maybePet.flatMap(pet  -­‐>  pet.getToy()); //  MAGIC!  :) String  toyName  =   jack.getPet().flatMap(Pet::getToy).map(Toy::getName).orElse("Default"); System.out.println(toyName); } }
  84. Java  SE  8  Date  and  Time • Why  need  for

     another  date  and  time  library? – Existing  classes  on  Thread-­‐safe  and  exhibit  poor  API   Design – Has  lead  to  third-­‐party  options  about  Date  and  Time   libraries • New  API – Objects  immutable  (no  setX – methods)  and   therefore  Thread-­‐safe – Clear  and  Fluent  API – Extensible  (you  can  build  your  own  calendar  system)
  85. Packages • java.time – Date,  Time,  Date  and  Time  combined,

     Time  zones,   Duration  and  Clocks • java.time.chrono – Alternative  calendar  systems  (other  than  ISO-­‐8601)  like   Buddhist • java.time.format – Formatting  times  in  different  formats • java.time.temporal – Formatting  and  parsing  dates  and  times • java.time.zone – Classes  for  time  zones
  86. java.time.DayOfWeek import  java.time.*; import  java.time.format.TextStyle; import  java.util.Locale; public  class  Main

     { public  static  void  main(String[]  args)  { //  MONDAY System.out.println(DayOfWeek.MONDAY); //  AUGUST System.out.println(Month.AUGUST); //  THURSDAY System.out.println(DayOfWeek.MONDAY.plus(3)); Locale  locale  =  Locale.getDefault(); //  Gets  the  textual  representation //  Mon System.out.println(DayOfWeek.MONDAY.getDisplayName(TextStyle.SHORT,  locale)); //  Aug System.out.println(Month.AUGUST.getDisplayName(TextStyle.SHORT,  locale)); } }
  87. java.time.LocalDate import   java.time.DayOfWeek; import   java.time.LocalDate; import   java.time.MonthDay;

    public   class   Main   { public   static   void   main(String[]   args)   { //  Year-­‐month-­‐day   in  ISO //        Good   for   birthdays,   wedding   dates LocalDate   localDate   =  LocalDate.now(); //  2015-­‐08-­‐19 System.out.println(localDate.toString()); LocalDate   christmas   =  LocalDate.of(2015,   12,   24); //  2015-­‐12-­‐24 System.out.println(christmas.toString()); LocalDate   birthday   =  LocalDate.of(1976,   2,   3); //  Get   day   of  week DayOfWeek   day   =  birthday.getDayOfWeek(); //  TUESDAY System.out.println(day); //  Also   classes //        YearMonth,   MonthDay,   Year MonthDay   md  =  MonthDay.of(12,   24); //  -­‐-­‐12-­‐24 System.out.println(md); } }
  88. java.time.LocalTime import  java.time.LocalDateTime; import  java.time.LocalTime; public  class  Main  { public

     static  void  main(String[]   args)  { //  For  human  -­‐ based  time LocalTime  sec  =  LocalTime.now(); //  10:18:35.011 System.out.println(sec.toString()); //  10:18 System.out.println(""   +  sec.getHour()  +  ":"  +  sec.getMinute()); //  Also  LocalDateTime LocalDateTime   dateSec  =  LocalDateTime.now(); //  2015-­‐08-­‐19T10:18:35.075 System.out.println(dateSec.toString()); } }
  89. java.time.Instant import  java.time.Instant; public  class  Main  { public  static  void

     main(String[]   args)  { //  Good  for  time  stamp  to  represent  machine  time //  Counts  time  beginning  from  1970-­‐01-­‐01T00:00:00Z Instant  now  =  Instant.now(); //  2015-­‐08-­‐19T07:25:33.361Z System.out.println(now); Instant  oneHourLater  =  now.plusSeconds(60   *  60); //  2015-­‐08-­‐19T08:23:44.110Z System.out.println(oneHourLater); } }
  90. java.time.Duration import  java.time.Duration; import  java.time.Instant; public  class  Main  { public

     static  void  main(String[]   args)  { Instant  now  =  Instant.now(); Instant  oneHourLater  =  now.plusSeconds(60   *  60); //  Duration  is  good  for  counting  duration  between  to  Instants:  60 Duration  duration  =  Duration.between(now,   oneHourLater); System.out.println(duration.toMinutes()); } }
  91. Java  8  New  Features • Lambdas – Method  references,  Default

     methods • Collections:  Stream  API • Optionals • Date  – Time  Package • Also  lot  of  smaller  changes