java 8: more readable and flexible code

111
Wri$ng more concise and flexible code with Java 8 RaoulGabriel Urma @raoulUK 1

Upload: weareesynergy

Post on 10-May-2015

736 views

Category:

Technology


4 download

DESCRIPTION

In this presentation we introduce Java 8’s main new features and show how you can benefit from them to write code that is more readable and more flexible to requirement changes. We will show how: 1) Lambda expressions and behaviour parameterisation let you write concise code that can cope for requirement changes 2) The new Streams API lets you express complex data process queries in a succinct way while automatically leveraging your multi-core architecture 3) Using the new Optional class can let you reduce unexpected NullPointer exceptions 4) Default methods bring a form of multi-inheritance to Java

TRANSCRIPT

Page 1: Java 8: more readable and flexible code

Wri$ng  more  concise  and  flexible  code  with  Java  8  

Raoul-­‐Gabriel  Urma  @raoulUK  

1  

Page 2: Java 8: more readable and flexible code

uname  -­‐a  •  PhD  at  University  of  Cambridge  (2011  -­‐  current)  –  Source  code  analysis,    automated  refactoring,  type  systems,  programming  languages  

•  MEng  Imperial  College  London  (2007  -­‐  2011)    •  Google  (Python  team),  Oracle  (Java  team),  Goldman  Sachs,  

eBay  •  Regular  author  for  Oracle  Java  Magazine  •  Conference  speaker:  Fosdem,  Devoxx…  

2  

Page 3: Java 8: more readable and flexible code

What  I’m  going  to  cover  

•  Why  Java  8?  (5min)  •  Behaviour  parameterisa$on  (10min)  •  Lambda  expressions  (20min)  •  Streams  (15min)  •  Op$onal  (5min)  •  Default  methods  (10min)  

3  

Page 4: Java 8: more readable and flexible code

Java  8  in  Ac$on:  Lambdas,  Streams  and  func$onal-­‐style  programming  

4  

•  Co-­‐authored  with  Mario  Fusco  &  Alan  Mycro`  •  Most  complete  book  on  Java  8  

h"p://manning.com/urma  

Page 5: Java 8: more readable and flexible code

Why  Java  8  

Before:  Collec$ons.sort(inventory,  new  Comparator<Apple>()  {            public  int  compare(Apple  a1,  Apple  a2){                  return  a1.getWeight().compareTo(a2.getWeight());            }  });    

A5er:  inventory.sort(comparing(Apple::getWeight));  

5  

Page 6: Java 8: more readable and flexible code

Why  Java  8?  

6  

List<Dish>  lowCaloricDishes  =  new  ArrayList<>();  for(Dish  d:  dishes){          if(d.getCalories()  <  400){                  lowCaloricDishes.add(d);          }  }    List<String>  lowCaloricDishesName  =  new  ArrayList<>();  Collec$ons.sort(lowCaloricDishes  ,  new  Comparator<Dish>()  {          public  int  compare(Dish  d1,  Dish  d2){                  return  Integer.compare(d1.getCalories(),  d2.getCalories());          }  });    for(Dish  d:  lowCaloricDishes){          lowCaloricDishesName.add(d.getName());  }     6  

sor$ng  by  calories  

filtering  low  calories  

Extract  names  

Page 7: Java 8: more readable and flexible code

Why  Java  8?  

7  7  

List<String>  lowCaloricDishesName  =                                  dishes.stream()                                            .filter(d  -­‐>  d.getCalories()  <  400)                                            .sorted(comparing(Dish::getCalories))                                            .map(Dish::getName)                                            .collect(toList());  

Page 8: Java 8: more readable and flexible code

Why  Java  8?    (  as  seen  by  language  designers)  

•  Commodity  CPUs  are  mul$core  (e.g.  4  cores)  •  Analogy:  you  have  4  assistants,  in  theory  you  could  get  the  work  done  4  $mes  faster!  

•  In  prac$ce:    –  it’s  hard  because  you  now  have  to  figure  out  how  to  distribute  a  piece  of  work  amongst  4  people.    

–  It’s  easier  to  just  pass  the  whole  piece  of  work  to  one  person.  

8  

Page 9: Java 8: more readable and flexible code

Why  Java  8?    (  as  seen  by  language  designers)  

•  Vast  majority  of  Java  programs  use  only  one  of  these  cores  and  leave  the  others  idle  

•  Why?  wri$ng  efficient  parallel  code  is  hard  – summing  an  array  with  a  for  loop  is  easy  – how  to  sum  an  array  on  4  cores?  

9  

Page 10: Java 8: more readable and flexible code

Why  Java  8?    (  as  seen  by  language  designers)  

•  Java  8  introduces  features  that  make  parallel  data  processing  easier  

•  Driven  from  three  concepts:  – stream  processing  – behaviour  parameterisa$on  ("passing  code")  – no  shared  mutable  data  

10  

Page 11: Java 8: more readable and flexible code

Stream  processing  

 cat  file1  file2  |  tr  "[A-­‐Z]"  "[a-­‐z]"  |  sort  |  tail  -­‐3      

11  

!

Page 12: Java 8: more readable and flexible code

Stream  processing  List<String>  lowCaloricDishesName  =          dishes.parallelStream()                                .filter(d  -­‐>  d.getCalories()  <  400)                                .sorted(comparing(Dish::getCalories))                                .map(Dish::getName)                                .collect(toList());  

12  

stream  processing  

Page 13: Java 8: more readable and flexible code

Behaviour  parameterisa$on  

13  

Page 14: Java 8: more readable and flexible code

Behaviour  parameterisa$on    

List<String>  lowCaloricDishesName  =          dishes.parallel()                                .filter(d  -­‐>  d.getCalories()  <  400)                                .sorted(comparing(Dish::getCalories))                                .map(Dish::getName)                                .collect(toList());  

14  

lambda  expression  

method  reference  

Page 15: Java 8: more readable and flexible code

No  shared  mutable  data  List<String>  lowCaloricDishesName  =          dishes.parallelStream()                                .filter(d  -­‐>  d.getCalories()  <  400)                                .sorted(comparing(Dish::getCalories))                                .map(Dish::getName)                                .collect(toList());  

15  

Can  be  duplicated  and  ran  on  disjoint  part  of  input  

Page 16: Java 8: more readable and flexible code

Java  8  

•  Introduces  a  concise  way  to  pass  behaviour  –  lambda  expressions,  method  references  

•  Introduces  an  API  to  process  data  in  parallel  – Streams  API  – several  opera$ons  such  as  filter,  map,  reduce  can  be  parameterised  with  lambdas  

•  Also:  default  methods  (more  later)  – more  flexible  inheritance  

16  

Page 17: Java 8: more readable and flexible code

Behaviour  parameterisa$on  

•  Goal:  abstract  over  behaviour  – Do  <something>  for  every  element  in  a  list  – Do  <something>  else  when  the  list  is  finished  –   Do  <yet  something  else>  if  an  error  occurs  

•  Why  should  you  care?  – Adapt  to  changing  requirements  –  Java  8  Streams  API  heavily  relies  on  it  

17  

Page 18: Java 8: more readable and flexible code

1st  awempt:  fitering  green  apples  public  sta$c  List<Apple>  filterGreenApples(List<Apple>  inventory)  {            List<Apple>  result  =  new  ArrayList<>();            for(Apple  apple:  inventory){                  if("green".equals(apple.getColor()  )  {                          result.add(apple);                  }          }          return  result;  }  

18  

Page 19: Java 8: more readable and flexible code

2nd  awempt:  abstrac$ng  color  public  sta$c  List<Apple>    filterApplesByColour(List<Apple>  inventory,  String  color)  {          List<Apple>  result  =  new  ArrayList<>();            for  (Apple  apple:  inventory){                  if  (apple.getColor().equals(color)))  {                          result.add(apple);  }                  }                return  result;  }  

19  

List<Apple>  greenApples  =  filterApplesByColor(inventory,  "green");    List<Apple>  redApples  =  filterApplesByColor(inventory,  "red");  

Page 20: Java 8: more readable and flexible code

2nd  awempt:  abstrac$ng  weight  public  sta$c  List<Apple>    filterApplesByWeight(List<Apple>  inventory,  int  weight)  {          List<Apple>  result  =  new  ArrayList<>();            for  (Apple  apple:  inventory){                  if  (apple.getWeight()  >  weight)  {                          result.add(apple);  }                  }                return  result;  }  

20  

List<Apple>  heavyApples  =  filterApplesByWeight(inventory,    150);    List<Apple>  megaHeavyApples  =  filterApplesByWeight(inventory,    250);  

Page 21: Java 8: more readable and flexible code

3rd  awempt:  filtering  with  everything  

public  sta$c  List<Apple>    filter  (List<Apple>  inventory,  String  color,  int  weight,  boolean  flag)  {          List<Apple>  result  =  new  ArrayList<>();          for  (Apple  apple:  inventory){                  if  (  (flag  &&  apple.getColor().equals(color))                              ||  (!flag  &&  apple.getWeight()  >  weight)  ){                          result.add(apple);  }          }          return  result;  }  

21  

List<Apple>  greenApples  =  filter(inventory,  "green",  0,  true);  List<Apple>  heavyApples  =  filter(inventory,  "",  150,  false);  

Page 22: Java 8: more readable and flexible code

4th  (a)  awempt:  modeling  selec$on  criteria  

public  interface  ApplePredicate{            public  boolean  test  (Apple  apple);  }    public  class  AppleWeightPredicate  implements  ApplePredicate{            public  boolean  test(Apple  apple){                  return  apple.getWeight()  >  150;            }  }  public  class  AppleColorPredicate  implements  ApplePredicate{          public  boolean  test(Apple  apple){                  return  "green".equals(apple.getColor());            }  }  

22  

Page 23: Java 8: more readable and flexible code

4th  (a)  awempt:  modeling  selec$on  criteria  

23  

Page 24: Java 8: more readable and flexible code

4th  (b)  awempt:  filtering  by  an  abstract  criteria  

public  sta$c  List<Apple>    filter(List<Apple>  inventory,  ApplePredicate  p){          List<Apple>  result  =  new  ArrayList<>();          for(Apple  apple:  inventory){                  if(p.test(apple)){                          result.add(apple);  �                }          }          return  result;  }  

24  

Page 25: Java 8: more readable and flexible code

Let’s  pause  for  a  liwle  bit  

•  Our  code  is  much  more  flexible!  –  can  create  any  kinds  of  selec$on  criteria  on  an  Apple  –  re-­‐use  of  code  for  filter  

•  However,  declaring  many  selec$on  criterias  using  classes  is  verbose…  L  – we  have  the  right  abstrac$on  but  not  good  concision  – we  need  a  bewer  way  to  create  and  pass  behaviours  

25  

Page 26: Java 8: more readable and flexible code

5th  awempt:  anonymous  classes  List<Apple>  result  =  filter(inventory,  new  ApplePredicate()  {          public  boolean  test(Apple  apple){                  return  "red".equals.(apple.getColor());          }  });    List<Apple>  result  =  filter(inventory,  new  ApplePredicate()  {          public  boolean  test(Apple  apple){                  return  apple.getWeight()  >  150;          }  });     26  

Page 27: Java 8: more readable and flexible code

6th  awempt:  Java  8  lambdas  List<Apple>  result  =            filter(inventory,  (Apple  apple)  -­‐>  "red".equals.(apple.getColor()));    List<Apple>  result  =            filter(inventory,  (Apple  apple)  -­‐>  apple.getWeight()  >  150);    

27  

Great  because  closer  to  problem  statement!  

Page 28: Java 8: more readable and flexible code

7th  awempt:  abstrac$ng  over  the    list  type    

public  sta$c  <T>  List<T>  filter  (List<T>  list,  Predicate<T>  p)  {            List<T>  result  =  new  ArrayList<>();            for(T  e:  list){                  if(p.test(e))  {                          result.add(e);                  }          }          return  result;  }  

28  

Page 29: Java 8: more readable and flexible code

8th  awempt:  Java  8  lambdas  again  List<String>  result  =            filter(strings,  (String  s)  -­‐>    s.endsWith("JDK"));    List<Integer>  result  =            filter(numbers,  (Integer  i)  -­‐>  i  %  2  ==  0);    List<Apple>  result  =            filter(inventory,  (Apple  a)  -­‐>  apple.getWeight()  >  150);    

29  

Page 30: Java 8: more readable and flexible code

Moral  of  the  story  

•  Behaviour  parameterisa$on  lets  you  write  more  flexible  code  – Adapt  for  changes  – Avoids  code  duplica$on  

•  To  encourage  this  style  of  programming  we  need  a  concise  way  to  create  and  pass  behaviours  –  Java  8  brings  lambda  expressions  to  help!  

30  

Page 31: Java 8: more readable and flexible code

Flexible  

Concise  

Anonymous  classes  

Verbose  

Rigid  

Lambdas  Class  +  Instance  

Value  parameterisa$on  

Behaviour  parameterisa$on  

Value  vs  Behaviour  parameterisa$on  

Page 32: Java 8: more readable and flexible code

Lambda  expressions:  what  is  it?  

•  A  lambda  expression  is:    – a  kind  of  anonymous  func$on    –  that  can  be  passed  around:    –  It  doesn’t  have  a  name,  but  it  has  a  list  of  parameters,  a  body,  a  return  type,  and  also  possibly  a  list  of  excep$ons  that  can  be  thrown.    

32  

Page 33: Java 8: more readable and flexible code

In  a  nutshell  

33  

Page 34: Java 8: more readable and flexible code

Lambda  expressions:  what  is  it?  

•  A  lambda  expression  is:    – a  kind  of  anonymous  func$on      

•  Anonymous:  doesn’t  have  an  explicit  name  like  a  method:  less  to  write  and  think  about!  

•  Func$on:  not  associated  to  a  class  like  a  method  is  

34  

Page 35: Java 8: more readable and flexible code

Lambda  expressions:  what  is  it?  

•  A  lambda  expression  is:    – a  kind  of  anonymous  func$on    –  that  can  be  passed  around:    

•  Passed  around:  A  lambda  expression  can  be  passed  as  argument  to  a  method  or  stored  in  a  variable  

35  

Page 36: Java 8: more readable and flexible code

Lambda  expressions:  what  is  it?  

•  A  lambda  expression  is:    – a  kind  of  anonymous  func$on    –  that  can  be  passed  around:    –  it  doesn’t  have  a  name,  but  it  has  a  list  of  parameters,  a  body,  a  return  type,  and  also  possibly  a  list  of  excep$ons  that  can  be  thrown.  

•   Concise:  you  don’t  need  to  write  a  lot  of  boilerplate  like  you  do  for  anonymous  classes.  

36  

Page 37: Java 8: more readable and flexible code

Goal  

•  Goal:  let  you  pass  a  piece  of  behaviour/code  in  a  concise  way  

•  You  can  cope  with  changing  requirements  by  using  a  behaviour,  represented  by  a  lambda,  as  a  parameter  to  a  method  

•  You  no  longer  need  to  choose  between  abstracaon  and  concision!    

37  

Page 38: Java 8: more readable and flexible code

Before/A`er  

Before:  inventory.sort(new  Comparator<Apple>()  {            public  int  compare(Apple  a1,  Apple  a2){                  return  a1.getWeight().compareTo(a2.getWeight());            }  });  

 

A5er:  inventory.sort((Apple  a1,  Apple  a2)  -­‐>  a1.getWeight().compareTo(a2.getWeight()));  

38  

Page 39: Java 8: more readable and flexible code

Examples  

39  

Use  case   Example  of  lambda  A  boolean  expression   (List<String>  list)  -­‐>  list.isEmpty()  Crea$ng  objects   ()  -­‐>  new  Apple(10)  Consuming  from  an  object   (Apple  a)  -­‐>  System.out.println(a.getWeight())  Select/extract  from  an  object   (String  s)  -­‐>  s.length()  Combine  two  values   (int  a,  int  b)  -­‐>  a  *  b  Compare  two  objects   (Apple  a1,  Apple  a2)  -­‐>  

a1.getWeight().compareTo(a2.getWeight())  

Page 40: Java 8: more readable and flexible code

Where  and  how  to  use  lambdas?  

40  

•  Java  lets  you  pass  expressions  only  where  a  type  is  expected  

•  So  what’s  the  type  of  a  lambda  expression?  

Page 41: Java 8: more readable and flexible code

Func$onal  interface  (1)  

41  

•  The  type  of  a  lambda  expression  is  essen$ally  a  funcaonal  interface  

•  A  func$onal  interface  is  an  interface  that  declares  exactly  one  (abstract)  method.    

Page 42: Java 8: more readable and flexible code

Func$onal  interface  (2)  

42  

//  java.u$l.Comparator  public  interface  Comparator<T>  {          public  int  compare(T  o1,  T  o2);    }    public  interface  Runnable  {          public  void  run();    }    public  interface  ApplePredicate  {            public  boolean  test  (Apple  a);  }  

Page 43: Java 8: more readable and flexible code

Func$onal  interface  &  Lambdas  

43  

•  The  signature  of  the  abstract  method  of  the  func$onal  interface  essen$ally  describes  the  signature  of  the  lambda  expression.  

•  Lambda  expressions  let  you  provide  the  implementa$on  of  the  abstract  method  of  a  func$onal  interface  directly  inline  and  treat  the  whole  expression  as  an  instance  of  a  func$onal  interface.  

Page 44: Java 8: more readable and flexible code

Func$onal  interface  &  Lambdas  

44  

Runnable  r1  =  ()  -­‐>  System.out.println("Hello  World  1");  Runnable  r2  =  new  Runnable(){            public  void  run(){                  System.out.println("Hello  World  2");            }  }  public  void  process(Runnable  r){            r.run();  }  process(r1);    process(r2);    process(()  -­‐>  System.out.println("Hello  World  3"));  

Page 45: Java 8: more readable and flexible code

Execute  Around  Pawern  

45  

Open    ressource  

Do  some  processing  

Close  ressource  

Page 46: Java 8: more readable and flexible code

Execute  Around  Pawern  

46  

public  sta$c  String  processFile()  throws  IOExcep$on  {          try  (BufferedReader  br  =                                                      new  BufferedReader(new  FileReader("data.txt")))  {                  return  br.readLine();            }  }    

•  This  current  code  is  limited.  You  can  read  only  the  first  line  of  the  file.    

 

Page 47: Java 8: more readable and flexible code

What  we  want  

47  

String  result  =            processFile((BufferedReader  br)  -­‐>  br.readLine());      String  result  =            processFile((BufferedReader  br)  -­‐>  br.readLine()  +  br.readLine());      

Page 48: Java 8: more readable and flexible code

Step  1:  Introducing  func$onal  interface  

48  

public  interface  BufferedReaderProcessor  {          public  String  process(BufferedReader  b)  throws  IOExcep$on;    }    public  sta$c  String  processFile(BufferedReaderProcessor  p)  throws  IOExcep$on  {  ...    }      

Page 49: Java 8: more readable and flexible code

Step  2:  Execu$ng  a  behaviour  

49  

public  sta$c  String    processFile(BufferedReaderProcessor  p)  throws  IOExcep$on  {          try  (BufferedReader  br  =                                                new  BufferedReader(new  FileReader("data.txt")))  {                  return  p.process(br);            }  }    String  result  =            processFile((BufferedReader  br)  -­‐>  br.readLine());      String  result  =            processFile((BufferedReader  br)  -­‐>  br.readLine()  +  br.readLine());        

Page 50: Java 8: more readable and flexible code

Lots  of  func$onal  interfaces  

50  

Funcaonal  interface   Lambda  signature  Predicate<T>   T  -­‐>  boolean  Consumer<T>   T  -­‐>  void  Func$on<T,  R>   T  -­‐>  R  Supplier<T>   ()  -­‐>  T  UnaryOperator<T>   T  -­‐>  T  Binaryoperator<T>   (T,  T)  -­‐>  T  BiFunc$on<T,  U,  R>     (T,  U)  -­‐>  R  

•  Have  a  look  in  java.u$l.func$on.*  

Page 51: Java 8: more readable and flexible code

Method  references  

51  

•  Method  references  let  you  reuse  exis$ng  method  defini$ons  and  pass  them  just  like  lambdas.  «  First-­‐class  »  func$ons  

•  Just  a  syntac'c  suggar  to  lambdas  

Before:  (Apple  a)  -­‐>  a.getWeight()  A5er:  Apple::getWeight    Before:  (str,  i)  -­‐>  str.substring(i)  A5er:  String::substring  

 

Page 52: Java 8: more readable and flexible code

Recipes  

52  

Page 53: Java 8: more readable and flexible code

Bewer  code  with  Java  8:    a  prac$cal  example  

53  

 public  class  AppleComparator  implements  Comparator<Apple>  {            public  int  compare(Apple  a1,  Apple  a2){                  return  a1.getWeight().compareTo(a2.getWeight());          }  }    inventory.sort(new  AppleComparator());  

Page 54: Java 8: more readable and flexible code

Anonymous  class  

54  

inventory.sort(new  Comparator<Apple>()  {            public  int  compare(Apple  a1,  Apple  a2){                  return  a1.getWeight().compareTo(a2.getWeight());            }  });  

Page 55: Java 8: more readable and flexible code

Lambdas  

55  

inventory.sort(      (Apple  a1,  Apple  a2)  -­‐>  a1.getWeight().compareTo(a2.getWeight())  );      

Page 56: Java 8: more readable and flexible code

Lambdas  

56  

inventory.sort(      (Apple  a1,  Apple  a2)  -­‐>  a1.getWeight().compareTo(a2.getWeight())  );      With  type  inference:  inventory.sort(      (a1,  a2)  -­‐>  a1.getWeight().compareTo(a2.getWeight())  );    

Page 57: Java 8: more readable and flexible code

A  bit  of  help  from  library  

57  

Comparator<Apple>  byWeight  =            Comparator.comparing((Apple  a)  -­‐>  a.getWeight());    inventory.sort(byWeight);      

Page 58: Java 8: more readable and flexible code

Method  references  

58  

Comparator<Apple>  byWeight  =            Comparator.comparing(Apple::getWeight);    inventory.sort(byWeight);      

Page 59: Java 8: more readable and flexible code

Tidy  up  

59  

import  sta$c  java.u$l.Comparator.comparing;  inventory.sort(comparing(Apple::getWeight));      Reads  like  probable  statement!  

Page 60: Java 8: more readable and flexible code

Streams  

60  

•  Nearly  every  Java  applica$ons  makes  and  processes  collec$ons  

•  However  processing  collec$ons  is  far  from  perfect:  – SQL  like  opera$ons?  – How  to  efficiently  process  large  collec$ons?  

Page 61: Java 8: more readable and flexible code

SQL-­‐like  opera$ons  

61  

•  Many  processing  pawerns  are  SQL-­‐like  – finding  a  transac$on  with  highest  value  – grouping  transac$ons  related  to  grocery  shopping  

•  Re-­‐implemented  every  $me  •  SQL  is  declaraave  – express  what  you  expect  not  how  to  implement  a  query  

– SELECT  id,  MAX(value)  from  transac$ons  

Page 62: Java 8: more readable and flexible code

Example:  Java  7  

62  

List<Transac$on>  groceryTransac$ons  =  new  Arraylist<>();  for(Transac$on  t:  transac$ons){      if(t.getType()  ==  Transac$on.GROCERY){          groceryTransac$ons.add(t);      }  }  Collec$ons.sort(groceryTransac$ons,  new  Comparator(){      public  int  compare(Transac$on  t1,  Transac$on  t2){          return  t2.getValue().compareTo(t1.getValue());      }  });  List<Integer>  transac$onIds  =  new  ArrayList<>();  for(Transac$on  t:  groceryTransac$ons){      transac$onsIds.add(t.getId());  }        

sor$ng  by  decreasing  value  

filtering  grocery  transac$ons  

extract  Ids  

Page 63: Java 8: more readable and flexible code

Example:  Java  8  

63  

List<Integer>  transac$onsIds  =            transacaons.stream()                                  .filter(t  -­‐>  t.getType()  ==  Transac$on.GROCERY)                                  .sorted(comparing(Transac$on::getValue).reversed())                                  .map(Transac$on::getId)                                  .collect(toList());  

Page 64: Java 8: more readable and flexible code

Example:  Java  8  -­‐  parallel  

64  

List<Integer>  transac$onsIds  =            transacaons.parallelStream()                                  .filter(t  -­‐>  t.getType()  ==  Transac$on.GROCERY)                                  .sorted(comparing(Transac$on::getValue).reversed())                                  .map(Transac$on::getId)                                  .collect(toList());  

Page 65: Java 8: more readable and flexible code

Ok  cool  –  so  what’s  a  Stream?  

65  

•  Informal:  a  fancy  iterator  with  database-­‐like  opera$ons  

•  Formal:  A  sequence  of  elements  from  a  source  that  supports  aggregate  opera$ons.  

Page 66: Java 8: more readable and flexible code

Ok  cool  –  so  what’s  a  Stream?  

66  

•  Sequence  of  elements:  a  stream  provides  an  interface  to  a  sequenced  set  of  values  of  a  specific  element  type.  However,  streams  don’t  actually  store  elements,  they  are  computed  on  demand.  

Page 67: Java 8: more readable and flexible code

Ok  cool  –  so  what’s  a  Stream?  

67  

•  Source:  Streams  consume  from  a  data-­‐providing  source  such  as  Collec$ons,  Arrays,  or  IO  resources.  

Page 68: Java 8: more readable and flexible code

Ok  cool  –  so  what’s  a  Stream?  

68  

•  Aggregate  operaaons:  Streams  support  SQL-­‐like  opera$ons  and  common  opera$ons  from  func$onal  programing  languages  such  as  filter,  map,  reduce,  find,  match,  sorted  etc.  

Page 69: Java 8: more readable and flexible code

Two  addi$onal  proper$es  

69  

•  Pipelining:  Many  stream  opera$ons  return  a  stream  themselves.  This  allows  opera$ons  to  be  chained  and  form  a  larger  pipeline  as  well  as  certain  op$misa$ons  (more  later).    

•  Internal  iteraaon:  In  contrast  to  collec$ons,  that  are  iterated  explicitly  (“external  itera$on”),  stream  opera$ons  do  the  itera$on  behind  the  scene  for  you.  

Page 70: Java 8: more readable and flexible code

70  

Pipelining  

•  Intermediate  operaaons:  return  a  Stream  and  can  be  “connected”  

•  Terminal  operaaons:  computes  the  result  of  the  pipeline  

   

Intermediate  opera$ons   Terminal  opera$on  

Page 71: Java 8: more readable and flexible code

71  

Internal  Itera$on  

Page 72: Java 8: more readable and flexible code

72  

Page 73: Java 8: more readable and flexible code

Laziness  &  short-­‐circui$ng  

73  

List<Integer>  numbers  =  Arrays.asList(1,  2,  3,  4,  5,  6,  7,  8);  List<Integer>  twoEvenSquares  =            numbers.stream()                        .filter(n  -­‐>  n  %  2  ==  0)                        .map(n  -­‐>  n  *  n)                        .limit(2)                        .collect(toList());  

Page 74: Java 8: more readable and flexible code

Laziness  &  loop  fusion  &  short-­‐circui$ng  

74  

List<Integer>  numbers  =  Arrays.asList(1,  2,  3,  4,  5,  6,  7,  8);  List<Integer>  twoEvenSquares  =            numbers.stream()                        .filter(n  -­‐>  n  %  2  ==  0)                        .map(n  -­‐>  n  *  n)                        .limit(2)                        .collect(toList());  

 •  filtering  1  •  filtering  2  •  mapping  2  •  filtering  3  •  filtering  4  •  mapping  4    

Page 75: Java 8: more readable and flexible code

Many  opera$ons  

75  

•  Filtering:  filter,  dis$nct,  limit,  skip  •  Finding/Matching:  anyMatch,  allMatch,  noneMatch,  findAny,  findFirst  

•  Mapping:  map,  flatMap  •  Reducing:  reduce  

Page 76: Java 8: more readable and flexible code

Streams:  much  more  (1)  Map<Dish.Type,  List<Dish>>  dishesbyType  =  new  HashMap<>();    for  (Dish  dish:  menu)  {    

 Dish.Type  type=  dish.getType();    List<Dish>  dishesForType  =  dishesbyType  .get(type);    if  (dishesForType  ==  null)  {      dishesForType  =  new  ArrayList<>();      dishesbyType  .put(type,  dishesForType);    }    dishesForType  .add(dish);  

}        

76  

Page 77: Java 8: more readable and flexible code

Streams:  much  more(2)  

77  

Map<Dish.Type,  List<Dish>>  dishesByType  =            menu.stream().collect(groupingBy(Dish::getType));    {FISH=[prawns,  salmon],  OTHER=[french  fries,  rice,  season  fruit,  pizza],  MEAT=[pork,  beef,  chicken]}      

Page 78: Java 8: more readable and flexible code

Streams:  much  more(3)  Map<Boolean,  Map<Dish.Type,  List<Dish>>>  vegetarianDishesByType  =    menu.stream().collect(    

   paraaoningBy(Dish::isVegetarian,  groupingBy(Dish::getType)));        •  Produces  a  two-­‐level  Map:  {false={FISH=[prawns,  salmon],  MEAT=[pork,  beef,  chicken]},  true={OTHER=[french  fries,  rice,  season  fruit,  pizza]}}    

78  

Page 79: Java 8: more readable and flexible code

Step  1:  sequen$al  for  loop  

public  sta$c  long  itera$veSum(long  n)  {                  long  result  =  0;                  for  (long  i  =  0;  i  <  n;  i++)  {                          result  +=  i;                  }                  return  result;          }    

79  

3ms  

Page 80: Java 8: more readable and flexible code

Step  2:  sequen$al  stream    public  sta$c  long  sequen$alSum(long  n)  {                  return  Stream.iterate(1L,  i  -­‐>  i  +  1)                                                                      .limit(n)                                                                      .reduce(Long::sum).get();          }  

80  

98ms  

Page 81: Java 8: more readable and flexible code

Step  3:  parallel  stream    public  sta$c  long  sequen$alSum(long  n)  {                  return  Stream.iterate(1L,  i  -­‐>  i  +  1).parallel()                                                                      .limit(n)                                                                      .reduce(Long::sum).get();          }  

81  

193ms!!  

Page 82: Java 8: more readable and flexible code

Step  4:  improved  sequen$al  stream  

 public  sta$c  long  rangedSum(long  n)  {                  return  LongStream.rangeClosed(1,  n)                                                                                    .reduce(Long::sum).getAsLong();          }  

82  

17ms  

Page 83: Java 8: more readable and flexible code

Step  5:  improved  parallel  stream    public  sta$c  long  rangedSum(long  n)  {                  return  LongStream.rangeClosed(1,  n).parallel()                                                                                    .reduce(Long::sum).getAsLong();          }  

83  

1ms  

Page 84: Java 8: more readable and flexible code

Streams:  much  more  (1)  

84  

•  Infinite  streams  •  Collectors:    – collect  – groupingBy  – par$$onBy  

 

Page 85: Java 8: more readable and flexible code

Op$onal<T>  

85  

•  A  new  class  added  in  Java8:  java.u$l.Op$onal  •  Indicates  the  presence  or  absence  of  a  value  •  has  a  bunch  of  method  to  simplify  and  force  “null”  checking  

 Op$onal<Transac$on>  optTransac$on  =            numbers.stream().findAny(t  -­‐>  t.getValue()  <  200);      

Page 86: Java 8: more readable and flexible code

Create  Op$onal  

86  

opt  =  Op$onal.of(notNull);      opt  =  Op$onal.ofNullable(mayBeNull);      opt  =  Op$onal.empty();  

Page 87: Java 8: more readable and flexible code

Op$onal:  do  something  if  there’s  a  value  

87  

Instead  of:  if(transac$on  !=  null){          System.out.println(t);  }    Write:  optTransac$on.ifPresent(System.out::println);  

Page 88: Java 8: more readable and flexible code

Op$onal:  reject  certain  values  

88  

Instead  of:  if(transac$on  !=  null  &&  transac$on.getId()  >  10){          System.out.println(t);  }    Write:  optTransac$on.filter(t  -­‐>  t.getId()  >  10)                                                        .ifPresent(System.out::println);  

Page 89: Java 8: more readable and flexible code

Op$onal:  transform  value  if  present  

89  

Instead  of:  if(transac$on  !=  null){          String  group  =  transac$on.getGroup();          if(“shopping”.equals(group)){                  System.out.println(t);          }  }  Write:  optTransac$on.map(Transac$on::getGroup)                                                        .filter(g  -­‐>  “shopping”.equals(g))                                                        .ifPresent(System.out::println);  

Page 90: Java 8: more readable and flexible code

Op$onal:  default  value  

90  

Instead  of:  int  len  =  (list  !=  null)?  list.size()  :  -­‐1;    Write:  int  len  =  list.map(List::size).orElse(-­‐1);  

Page 91: Java 8: more readable and flexible code

Op$onal:  nested  checking  

91  

Instead  of:  if(transac$on  ==  null){          return  “Unknown”;  }  Des$nator  des$nator  =  transac$on.getDes$nator();  if(des$nator  ==  null){          return  “Unknown”;  }  country  =  des$nator.getCountry();  if(country  ==  null){          return  “Unknown”;  }  return  country.getName()  !=  null  ?  country.getName()  :  “Unknown”;  

Page 92: Java 8: more readable and flexible code

Op$onal:  nested  checking  

92  

transac$on.flatMap(Transac$on::getDes$nator)                                          .flatMap(Transac$on::getCountry)                                          .map(Country::getName)                                          .orElse(“Unknown”);  

Page 93: Java 8: more readable and flexible code

Default  methods  

93  

•  Interfaces  in  Java  8  can  contain  implementa$on  code  

From  List.java:  default  void  sort(Comparator<?  super  E>  c){          Collec$ons.sort(this,  c);  }    

Page 94: Java 8: more readable and flexible code

Goal  

94  

•  Evolve  libraries  •  Adding  a  method  to  an  interface  is  source  incompa$ble  – all  implementers  need  to  support  the  method  –  recompiling  a  class  implemen$ng  the  interface  will  fail  

•  Providing  a  “default”  implementa$on  solves  the  problem  

Page 95: Java 8: more readable and flexible code

95  

Page 96: Java 8: more readable and flexible code

Applica$ons:  Op$onal  methods  

96  

interface  Iterator<T>  {            boolean  hasNext();            T  next();            default  void  remove()  {                    throw  new  UnsupportedOpera$onExcep$on();            }    }    

Page 97: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

97  

•  A  class  has  been  allowed  to  implement  mul$ple  interfaces  since  day  1  of  Java!  

public  class  ArrayList<E>    extends  AbstractList<E>    implements  List<E>,  RandomAccess,  Cloneable,  java.io.Serializable,  Iterable<E>,  Serializable  {    …  }  

 

Page 98: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

98  

Page 99: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

99  

public  interface  Sized  {          public  int  size();          public  default  boolean  isEmpty(){                  return  size()  ==  0;          }  }    

Page 100: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

100  

public  interface  Foreachable<T>  extends  Iterable<T>  {          public  default  void  forEach(Consumer<?  super  T>  block){                  for(T  e:  this){                          block.accept(e);                  }          }  }    

Page 101: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

101  

public  interface  Removeable<T>  extends  Iterable<T>  {          public  default  boolean  removeIf(Predicate<?  super  T>  filter){                  boolean  removed  =  false;                    Iterator<T>  each  =  iterator();                    while(each.hasNext())  {                            if(filter.test(each.next()))  {                                    each.remove();                                    removed  =  true;                            }                    }                    return  removed;            }  }    

Page 102: Java 8: more readable and flexible code

Applica$ons:  mul$ple  inheritance  

102  

Page 103: Java 8: more readable and flexible code

Resolu$on  rules  

103  

1.  Classes  always  win.  A  method  declara$on  in  the  class  or  a  superclass  takes  priority  over  any  default  method  declara$on.  2.  Otherwise,  the  method  with  the  same  signature  in  the  most  specific  default-­‐providing  interface  is  selected.  (If  B  extends  A,  B  is  more  specific  than  A).    

Page 104: Java 8: more readable and flexible code

Use  case  1  

104  

Page 105: Java 8: more readable and flexible code

Use  case  1  

105  

public  interface  A{          public  default  void  hello()  {                    System.out.println("Hello  from  A");          }  }  public  interface  B  extends  A{          public  default  void  hello()  {                    System.out.println("Hello  from  B");          }  }  public  class  C  implements  B,  A  {          public  sta$c  void  main(String...  args)  {                  new  C().hello();  //  ??          }  }    

Page 106: Java 8: more readable and flexible code

Use  case  2  (a)  

106  

public  class  D  implements  A{  }    public  class  C  extends  D  implements  B,  A  {          public  sta$c  void  main(String...  args)  {                  new  C().hello();  //  ??          }  }  

Page 107: Java 8: more readable and flexible code

Use  case  2  (b)  

107  

public  class  D  implements  A{            public  void  hello(){                  System.out.println(“Hello  from  D”);          }  }    public  class  C  extends  D  implements  B,  A  {          public  sta$c  void  main(String...  args)  {                  new  C().hello();  //  ??          }  }  

Page 108: Java 8: more readable and flexible code

Use  case  3  

108  

Page 109: Java 8: more readable and flexible code

Explicit  disambigua$on  

109  

public  class  C  implements  B,  A  {            public  void  hello(){                  B.super.hello();          }  }  

Page 110: Java 8: more readable and flexible code

Use  case  4  

110  

Page 111: Java 8: more readable and flexible code

More…  

111  

•  Func$onal  asynchronous  programming  with  CompleatableFuture  

•  Performance,  Spliterators  •  Recipes  using  Op$onal  •  Tools,  tes$ng  &  debugging  •  Func$onal  programming  in  Java  •  Good  ideas  from  Scala  •  Date/Time  API,  Java  bytecode  &  lambdas  

•  Get  the  book  Java  8  in  Acaon  to  find  out  more!!!  •  h"p://manning.com/urma/  38%  discount  code:  vturma01