Sei sulla pagina 1di 38

Lambdas

 and  Streams  in  JDK  8  

Simon  Ri4er  
Head  of  Java  Technology  Evangelism  
Oracle  Corp  
 
Twi4er:  @speakjava  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Safe  Harbor  Statement  
The  following  is  intended  to  outline  our  general  product  direcRon.  It  is  intended  for  
informaRon  purposes  only,  and  may  not  be  incorporated  into  any  contract.  It  is  not  a  
commitment  to  deliver  any  material,  code,  or  funcRonality,  and  should  not  be  relied  upon  
in  making  purchasing  decisions.  The  development,  release,  and  Rming  of  any  features  or  
funcRonality  described  for  Oracle’s  products  remains  at  the  sole  discreRon  of  Oracle.  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.       2  


Concurrency  in  Java   Project  Lambda  

Fork/Join  Framework  
java.util.concurrent   (jsr166y)  
(jsr166)  
Phasers,  etc  
java.lang.Thread   (jsr166)  

1.0 5.0 6
1996 … 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014
7 8
Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      
Lambdas  In  Java  
 

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


The  Problem:  External  IteraRon  
•  Our  code  controls  iteraRon  
List<Student>  students  =  ...  
double  highestScore  =  0.0;   •  Inherently  serial:  iterate  from  
beginning  to  end  
for  (Student  s  :  students)  {  
   if  (s.getGradYear()  ==  2011)  {   •  Not  thread-­‐safe      
       if  (s.getScore()  >  highestScore)   •  Business  logic  is  stateful  
           highestScore  =  s.score;   •  Mutable  accumulator  variable  
   }  
}  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Internal  IteraRon  With  Inner  Classes  
More  FuncRonal  
double  highestScore  =  students   •  IteraRon  handled  by  the  library  
   .filter(new  Predicate<Student>()  {   •  Not  inherently  serial  –  traversal  may  
       public  boolean  op(Student  s)  {   be  done  in  parallel  
           return  s.getGradYear()  ==  2011;  
•  Traversal  may  be  done  lazily  –  so  one  
       }   pass,  rather  than  three  
   })  
•  Thread  safe  –  client  logic  is  stateless  
   .map(new  Mapper<Student,Double>()  {  
       public  Double  extract(Student  s)  {   •  High  barrier  to  use  
           return  s.getScore();   – SyntacRcally  ugly  
       }  
   })  
   .max();  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Internal  IteraRon  With  Lambdas  
List<Student>  students  =  ...  
double  highestScore  =  students  
                     .filter(Student  s  -­‐>  s.getGradYear()  ==  2011)  
                     .map(Student  s  -­‐>  s.getScore())  
                     .max();  

•  More  readable  
•  More  abstract  
•  Less  error-­‐prone  

NOTE:  This  is  not  JDK8  code  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Lambda  Expressions  
Some  Details  
•  Lambda  expressions  represent  anonymous  funcRons  
– Same  structure  as  a  method  
•  typed  argument  list,  return  type,  set  of  thrown  excepRons,  and  a  body  
– Not  associated  with  a  class  
•  We  now  have  parameterised  behaviour,  not  just  values  
double  highestScore  =  students.  
                   filter(Student  s  -­‐>  s.getGradYear()  ==  2011).  
What                      map(Student  s  -­‐>  s.getScore())  
                   max();  

How  
Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      
Lambda  Expression  Types  
•  Single-­‐method  interfaces  are  used  extensively  in  Java  
– DefiniRon:  a  func2onal  interface  is  an  interface  with  one  abstract  method  
– Func2onal  interfaces  are  idenRfied  structurally  
– The  type  of  a  lambda  expression  will  be  a  func2onal  interface  
•  Lambda  expressions  provide  implementaRons  of  the  abstract  method  

interface  Comparator<T>    {  boolean  compare(T  x,  T  y);  }  


 interface  FileFilter          {  boolean  accept(File  x);  }  
 interface  Runnable              {  void  run();  }  
 interface  ActionListener  {  void  actionPerformed(…);  }  
 interface  Callable<T>        {  T  call();  }  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Local  Variable  Capture  

•  Lambda  expressions  can  refer  to  effec2vely  final  local  variables  from  the  
enclosing  scope  
•  EffecRvely  final:  A  variable  that  meets  the  requirements  for  final  variables  (i.e.,  
assigned  once),  even  if  not  explicitly  declared  final  
•  Closures  on  values,  not  variables  

void  expire(File  root,  long  before)  {    


   root.listFiles(File  p  -­‐>  p.lastModified()  <=  before);  
}  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


What  Does  ‘this’  Mean  For  Lambdas?  
•  ‘this’  refers  to  the  enclosing  object,  not  the  lambda  itself  
•  Think  of  ‘this’  as  a  final  predefined  local  
•  Remember  the  Lambda  is  an  anonymous  func2on  
–  It  is  not  associated  with  a  class  
–  Therefore  there  can  be  no  ‘this’  for  the  Lambda  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Referencing  Instance  Variables  
Which  are  not  final,  or  effecRvely  final  
 
class  DataProcessor  {  
   private  int  currentValue;  
 
   public  void  process()  {  
       DataSet  myData  =  myFactory.getDataSet();  
       dataSet.forEach(d  -­‐>  d.use(currentValue++));  
   }  
}  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Referencing  Instance  Variables  
The  compiler  helps  us  out  
 
class  DataProcessor  {  
   private  int  currentValue;  
 
   public  void  process()  {  
       DataSet  myData  =  myFactory.getDataSet();  
       dataSet.forEach(d  -­‐>  d.use(this.currentValue++);  
   }  
}  

‘this’  (which  is  effecRvely  final)  


inserted  by  the  compiler  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Type  Inference  
•  The  compiler  can  ogen  infer  parameter  types  in  a  lambda  expression  
§ Inferrence  based  on  the  target  funcRonal  interface’s  method  signature  

static  T  void  sort(List<T>  l,  Comparator<?  super  T>  c);  

List<String>  list  =  getList();  


Collections.sort(list,  (String  x,  String  y)  -­‐>  x.length()  -­‐  y.length());  

Collections.sort(list,  (x,  y)  -­‐>  x.length()  -­‐  y.length());  

•  Fully  staRcally  typed  (no  dynamic  typing  sneaking  in)  


– More  typing  with  less  typing  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Method  References  

•  Method  references  let  us  reuse  a  method  as  a  lambda  expression  

FileFilter  x  =  File  f  -­‐>  f.canRead();  

FileFilter  x  =  File::canRead;  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Constructor  References  

•  Same  concept  as  a  method  reference  


– For  the  constructor  

Factory<List<String>>  f  =  ()  -­‐>  return  new  ArrayList<String>();  

Replace  with  

Factory<List<String>>  f  =  ArrayList<String>::new;  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Library  EvoluRon  
 

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Library  EvoluRon  Goal  
• Requirement:  aggregate  operaRons  on  collecRons  
– New  methods  required  on  CollecRons  to  facilitate  this  

  int  heaviestBlueBlock  =  blocks  


                       .filter(b  -­‐>  b.getColor()  ==  BLUE)  
                       .map(Block::getWeight)  
                       .reduce(0,  Integer::max);  
 
• This  is  problemaRc  
– Can’t  add  new  methods  to  interfaces  without  modifying  all  implementaRons  
– Can’t  necessarily  find  or  control  all  implementaRons  
Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      
SoluRon:  Default  Methods  

• Specified  in  the  interface  


• From  the  caller’s  perspecRve,  just  an  ordinary  interface  method  
•  Provides  a  default  implementaRon  
•  Default  only  used  when  implementaRon  classes  do  not  provide  a  body  for  the  
extension  method  
•  ImplementaRon  classes  can  provide  a  be4er  version,  or  not  
interface  Collection<E>  {    
   default  Stream<E>  stream()  {    
       return  StreamSupport.stream(spliterator());  
   }    
}  
Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      
Virtual  Extension  Methods  
Stop  right  there!  
•  Err,  isn’t  this  implemenRng  mulRple  inheritance  for  Java?      
•  Yes,  but  Java  already  has  mulRple  inheritance  of  types  
•  This  adds  mulRple  inheritance  of  behavior  too  
•  But  not  state,  which  is  where  most  of  the  trouble  is  
•  Can  sRll  be  a  source  of  complexity    
•  Class  implements  two  interfaces,  both  of  which  have  default  methods  
•  Same  signature  
•  How  does  the  compiler  differenRate?  
•  StaRc  methods  also  allowed  in  interfaces  in  Java  SE  8  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


FuncRonal  Interface  DefiniRon  

•  Single  Abstract  Method  (SAM)  type  


•  A  funcRonal  interface  is  an  interface  that  has  one  abstract  method  
– Represents  a  single  funcRon  contract  
– Doesn’t  mean  it  only  has  one  method  
•  @FunctionalInterface  annotaRon  
– Helps  ensure  the  funcRonal  interface  contract  is  honoured  
– Compiler  error  if  not  a  SAM  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Lambdas  In  Full  Flow:  
Streams  
 

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Stream  Overview  
At  The  High  Level  
•  AbstracRon  for  specifying  aggregate  computaRons  
– Not  a  data  structure  
– Can  be  infinite  
•  Simplifies  the  descripRon  of  aggregate  computaRons  
– Exposes  opportuniRes  for  opRmisaRon  
– Fusing,  laziness  and  parallelism  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Stream  Overview  
Pipeline  
•  A  stream  pipeline  consists  of  three  types  of  things  
– A  source  
– Zero  or  more  intermediate  operaRons  
– A  terminal  operaRon  
•  Producing  a  result  or  a  side-­‐effect  
Source  
int  total  =  transactions.stream()  
   .filter(t  -­‐>  t.getBuyer().getCity().equals(“London”))  
   .mapToInt(Transaction::getPrice)  
   .sum();  
Intermediate  operaRon  
Terminal  operaRon  
Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      
Stream  Sources  
Many  Ways  To  Create  
•  From  collecRons  and  arrays  
– Collection.stream()  
– Collection.parallelStream()  
– Arrays.stream(T  array)  or  Stream.of()  
•  StaRc  factories  
– IntStream.range()  
– Files.walk()  
•  Roll  your  own  
– java.util.Spliterator  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Stream  Terminal  OperaRons  

•  The  pipeline  is  only  evaluated  when  the  terminal  operaRon  is  called  
– All  operaRons  can  execute  sequenRally  or  in  parallel  
– Intermediate  operaRons  can  be  merged  
•  Avoiding  mulRple  redundant  passes  on  data  
•  Short-­‐circuit  operaRons  (e.g.  findFirst)  
•  Lazy  evaluaRon  
– Stream  characterisRcs  help  idenRfy  opRmisaRons  
•  DISTINT  stream  passed  to  distinct()  is  a  no-­‐op  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Maps  and  FlatMaps  
Map  Values  in  a  Stream  

1-­‐to-­‐1  mapping  
Input  Stream   Output  Stream  
Map  

1-­‐to-­‐many  mapping  
Input  Stream   Output  Stream  
FlatMap  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


OpRonal  Class  
Helping  To  Eliminate  the  NullPointerException  
•  Terminal  operaRons  like  min(),  max(),  etc  do  not  return  a  direct  result  
•  Suppose  the  input  Stream  is  empty?  
•  Optional<T>  
– Container  for  an  object  reference  (null,  or  real  object)  
– Think  of  it  like  a  Stream  of  0  or  1  elements  
– use  get(),  ifPresent()  and  orElse()  to  access  the  stored  reference  
– Can  use  in  more  complex  ways:  filter(),  map(),  etc  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  1  
Convert  words  in  list  to  upper  case  

List<String>  output  =  wordList  


   .stream()  
   .map(String::toUpperCase)  
   .collect(Collectors.toList());  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  1  
Convert  words  in  list  to  upper  case  (in  parallel)  

List<String>  output  =  wordList  


   .parallelStream()  
   .map(String::toUpperCase)  
   .collect(Collectors.toList());  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  2  
Count  lines  in  a  file  
•  BufferedReader  has  new  method  
– Stream<String>  lines()  
 

long  count  =  bufferedReader  


   .lines()  
   .count();  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  3  
Join  lines  3-­‐4  into  a  single  string  

String  output  =  bufferedReader  


   .lines()  
   .skip(2)  
   .limit(2)  
   .collect(Collectors.joining());  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  4  
Collect  all  words  in  a  file  into  a  list  

List<String>  output  =  reader  


   .lines()  
   .flatMap(line  -­‐>  Stream.of(line.split(REGEXP)))  
   .filter(word  -­‐>  word.length()  >  0)  
   .collect(Collectors.toList());  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  5  
List  of  unique  words  in  lowercase,  sorted  by  length  

List<String>  output  =  reader  


   .lines()  
   .flatMap(line  -­‐>  Stream.of(line.split(REGEXP)))  
   .filter(word  -­‐>  word.length()  >  0)  
   .map(String::toLowerCase)  
   .distinct()  
   .sorted((x,  y)  -­‐>  x.length()  -­‐  y.length())  
   .collect(Collectors.toList());  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  6:  Real  World  
Infinite  stream  from  thermal  sensor  
private  int  double  currentTemperature;  
...  
 
thermalReader  
   .lines()  
   .mapToDouble(s  -­‐>    
             Double.parseDouble(s.substring(0,  s.length()  -­‐  1)))  
   .map(t  -­‐>  ((t  –  32)  *  5  /  9)  
   .filter(t  -­‐>  t  !=  currentTemperature)  
   .peek(t  -­‐>  listener.ifPresent(l  -­‐>  l.temperatureChanged(t)))  
   .forEach(t  -­‐>  currentTemperature  =  t);  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Example  6:  Real  World  
Infinite  stream  from  thermal  sensor  
private  int  double  currentTemperature;  
...  
 
thermalReader  
   .lines()  
   .mapToDouble(s  -­‐>    
             Double.parseDouble(s.substring(0,  s.length()  -­‐  )))  
   .map(t  -­‐>  ((t  –  32)  *  5  /  9)  
   .filter(t  -­‐>  t  !=  this.currentTemperature)  
   .peek(t  -­‐>  listener.ifPresent(l  -­‐>  l.temperatureChanged(t)))  
   .forEach(t  -­‐>  this.currentTemperature  =  t);  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Conclusions  

•  Java  needs  lambda  statements    


– Significant  improvements  in  exisRng  libraries  are  required  
•  Require  a  mechanism  for  interface  evoluRon  
– SoluRon:  virtual  extension  methods  
•  Bulk  operaRons  on  CollecRons  
– Much  simpler  with  Lambdas  
•  Java  SE  8  evolves  the  language,  libraries,  and  VM  together  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      


Simon  Ri4er  
Oracle  CorporarRon  
 
Twi4er:  @speakjava  

Copyright  ©  2014,  Oracle  and/or  its  affiliates.  All  rights  reserved.      

Potrebbero piacerti anche