Functional Programming Haim Michael May 14th , 2019 All logos, trade marks and brand names used in this presentation belong to the respective owners. lifemichael Java https://youtu.be/6uWjT-lVyZI https://youtu.be/0nMc6nozPzw
© 1996-2018 All Rights Reserved. Haim Michael Introduction ● Snowboarding. Learning. Coding. Teaching. More than 20 years of Practical Experience. lifemichael
© 1996-2018 All Rights Reserved. Haim Michael Introduction ● Professional Certifications Zend Certified Engineer in PHP Certified Java Professional Certified Java EE Web Component Developer OMG Certified UML Professional ● MBA (cum laude) from Tel-Aviv University Information Systems Management lifemichael
© 2008 Haim Michael 20151026 Introduction
© 2008 Haim Michael 20151026 Introduction  The main programming languages paradigms include the following. Imperative Paradigm The program includes statements executed one by one that change the state. Structured Paradigm Based on Imperative. The code has a more logical structure. Avoiding the goto statement.
© 2008 Haim Michael 20151026 Introduction Procedural Paradigm Based on Structured. The code is split into procedures been called in order to have a shorted code to maintain. Object Oriented Paradigm During the execution of our code objects are created in order to represent the things our code deals with. Objects are connected with each other. Methods can be invoked on these objects.
© 2008 Haim Michael 20151026 Introduction Event Driven Paradigm The control flow is determined mainly by the events (e.g. mouse clicks, loading of data ends). Declarative Paradigm The code defines what we want to get without getting into the logic of it nor the details.
© 2008 Haim Michael 20151026 Functional Programming  Functional programming is a programming paradigm that emphasizes the use of expressions and their evaluation and especially through the definition of functions that are treated as expressions. In addition, it avoids the complexity involved with state changes as the one when using objects and variables.
© 2008 Haim Michael 20151026 Functional Programming  The use of functions as expressions enable us getting more expressive code. In many cases we will exploit the power of recursion in order to get expressive succinct (expressed in few words) code.
© 2008 Haim Michael 20151026 Pure Functions
© 2008 Haim Michael 20151026 Pure Functions  When we define a function that always returns the same value for the very same arguments, and it doesn't depend on any hidden information or state and its evaluation of the result does not cause any observable side effects nor output then it is a pure function.  Pure functions are usually simpler and much easier to test and are very popular in functional programming.
© 2008 Haim Michael 20151026 Pure Functions  In order to write a pure function we should make sure that we write local only code.  Writing a lambda expression as a pure function is the common approach.
© 2008 Haim Michael 20151026 Lambda Expressions
© Haim Michael 2017. All Rights Reserved. Introduction  When dealing with an interface that includes one method only and the sole purpose of that interface is to allow us passing over functionality to another part of our program we can use the lambda expression as an alternative for the anonymous inner class.
© Haim Michael 2017. All Rights Reserved. Syntax  The lambda expression includes a comma separated list of formal parameters enclosed within parentheses (the data type of the parameters can be usually omitted). If there is only one parameter then we can omit the parentheses. ob -> ob.age<40
© Haim Michael 2017. All Rights Reserved. Syntax  The body includes a single expression or a statement block. We can include the return statement.
© Haim Michael 2017. All Rights Reserved. Simple Demo package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); } public int calculate(int a, int b, MathOperation op) { return op.execute(a, b); }
© Haim Michael 2017. All Rights Reserved. Simple Demo public static void main(String... args) { SimpleLambdaExpressionDemo myApp = new SimpleLambdaExpressionDemo(); MathOperation addition = (a, b) -> a + b; MathOperation subtraction = (a, b) -> a - b; int num = addition.execute(40, 2); System.out.println("40 + 2 = " + num); System.out.println("20 – 10 = " + myApp.calculate(20, 10, subtraction)); } }
© Haim Michael 2017. All Rights Reserved. Simple Demo The Output
© Haim Michael 2017. All Rights Reserved. Methods References  There are four types of methods references: reference to static method, reference to an instance method of a particular object, reference to an instance method of an arbitrary object of a specific type and reference to constructor.
© Haim Michael 2017. All Rights Reserved. Reference to Static Method  We can refer a static method by specifying the name of the class following with "::" and the name of the static method.
© Haim Michael 2017. All Rights Reserved. Reference to Static Method package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); }
© Haim Michael 2017. All Rights Reserved. Reference to Static Method public static void main(String... args) { MathOperation op = Utils::calcu; int num = op.execute(40, 2); System.out.println("40 * 2 = " + num); } } class Utils { public static int calcu(int a,int b) { return a*b; } }
© Haim Michael 2017. All Rights Reserved. Reference to Static Method The Output
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method  We can refer a specific instance method by specifying the reference for the object following with "::" and the name of the instance method.
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); }
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method public static void main(String... args) { Utils utils = new Utils(); MathOperation op = utils::calcu; int num = op.execute(40, 2); System.out.println("40 * 2 = " + num); } } class Utils { public int calcu(int a,int b) { System.out.println("calcu is called"); return a*b; } }
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method The Output
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object  We can refer a specific instance method without been specific about the object on which it should be invoked.  Instead of specifying the reference for a specific object we should specify the name of the class followed by :: and the name of the function.
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object public class SimpleLambdaExpressionDemo { public static void main(String... args) { Student[] students = { new Student(123123,98,"dave"), new Student(234233,88,"ron"), new Student(452343,82,"ram"), new Student(734344,64,"lara") }; Arrays.sort(students,Student::compareTo); for(Student std : students) { System.out.println(std); } } }
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object class Student implements Comparable<Student> { private double average; private int id; private String name; Student(int id, double avg, String name) { this.average = avg; this.id = id; this.name = name; }
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object @Override public String toString() { return id+" "+average+" "+name; } @Override public int compareTo(Student o) { if(this.average>o.average) { return 1; } else if(this.average<o.average) { return -1; } else return 0; } }
© Haim Michael 2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object The Output
© Haim Michael 2017. All Rights Reserved. Reference to Constructor  We can refer the default constructor in a class by writing the name of the class following with ::new.
© Haim Michael 2017. All Rights Reserved. Reference to Constructor public class ReferenceToConstructor { public static void main(String... args) { Student []students = new Student[8]; populate(students, Student::new); for(int i=0; i<students.length; i++) { System.out.println(students[i]); } } public static void populate( Student[] vec, StudentsGenerator ob) { for(int i=0; i<vec.length; i++) { vec[i] = ob.create(); } } }
© Haim Michael 2017. All Rights Reserved. Reference to Constructor interface StudentsGenerator { public Student create(); } class Student implements Comparable<Student> { private static int counter = 1; private static String[] names ={"david","moshe","anat","jake"}; private double average; private int id; private String name; Student() { id = counter++; name = names[(int)(names.length*Math.random())]; average = (int)(100*Math.random()); }
© Haim Michael 2017. All Rights Reserved. Reference to Constructor Student(int id, double avg, String name) { this.average = avg; this.id = id; this.name = name; } @Override public String toString() { return id+" "+average+" "+name; }
© Haim Michael 2017. All Rights Reserved. Reference to Constructor @Override public int compareTo(Student o) { if(this.average>o.average) { return 1; } else if(this.average<o.average) { return -1; } else return 0; } }
© Haim Michael 2017. All Rights Reserved. Reference to Constructor The Output
© 2008 Haim Michael 20151026 Higher Order Functions
© 2008 Haim Michael 20151026 Higher Order Functions  When the function we define receives another function (or functions) as an argument(s) or when its returned value is another function it will called an higher order function.
© 2008 Haim Michael 20151026 Streams
© 1996-2017 All Rights Reserved. Introduction  Java 8 introduces the possibility to represent a sequence of objects as a stream.  Using streams we can process the sequence of objects in a declarative.
© 1996-2017 All Rights Reserved. Stream of Collection  The stream() method returns a sequential stream composed of elements coming from a collection.
© 1996-2017 All Rights Reserved. Stream of Collection package com.lifemichael.samples; import java.util.function.*; import java.util.*; import java.util.stream.Stream; public class Program { public static void main(String[] args) { List<Integer> numbers = new LinkedList<Integer>(); numbers.add(24); numbers.add(13); numbers.add(43); numbers.add(45); numbers.add(12); Stream<Integer> stream = numbers.stream(); stream.filter(num->num%2==0). forEach(num->System.out.println(num)); } }
© 1996-2017 All Rights Reserved. Stream of Collection
© 1996-2017 All Rights Reserved. Stream of Array  The stream() method that was defined in the Arrays class allows us to create a stream out of an array we hold.
© 1996-2017 All Rights Reserved. Stream of Array String[] cities = new String[]{"Rome", "London", "Moscow", "Ashdod", "Haifa", "Eilat", "Zermatt"}; Stream<String> full = Arrays. stream(cities); Stream<String> partial = Arrays. stream(cities, 1, 3); full.forEach(str->System.out.println(str));
© 1996-2017 All Rights Reserved. Building Streams  Calling the builder static method in Stream we get a Stream.Builder<T> object. Calling builder we should specify the desired type, otherwise we will get a builder for stream of objects.
© 1996-2017 All Rights Reserved. Building Streams Stream.Builder<String> builder = Stream.<String>builder(); Stream<String> stream = builder. add("london"). add("Paris"). add("Zurich").build(); stream.forEach(str -> System.out.println(str));
© 1996-2017 All Rights Reserved. Infinite Streams  We can easily create infinite streams. We can do it either using the Stream.generate() or the Stream.iterate() functions.
© 1996-2017 All Rights Reserved. Infinite Streams  The Stream.generate static method receives a Supplier<T> object, that generates endless number of objects.  If we don't want the Supplier<T> object to work endlessly you better use the limit function in order to limit the size of the generated stream.
© 1996-2017 All Rights Reserved. Infinite Streams Stream<String> stream = Stream.generate(() -> String. valueOf((int(100*Math.random()))). limit(10); stream.forEach(str -> System.out.println(str));
© 1996-2017 All Rights Reserved. Infinite Streams  The Stream.iterate static method provides us with an alternative way for creating endless streams. The first argument this method receives is the first element of the stream it is going to generate. The second argument is an UnaryOperator object.
© 1996-2017 All Rights Reserved. Infinite Streams  If we don't want to get endless stream till the memory ends we better use the limit function in order to limit it.
© 1996-2017 All Rights Reserved. Infinite Streams Stream<Integer> stream = Stream. iterate(10, n -> n+5). limit(10); stream.forEach(data -> System.out.println(data));
© 1996-2017 All Rights Reserved. Empty Streams  The empty() method was defined as a static method in Stream.  Calling this method we will get an empty stream. It is a useful method when developing a method that should return a reference for a Stream object. Instead of returning null we can easily return an empty stream.
© 1996-2017 All Rights Reserved. Empty Streams public class Main { public static void main(String[] args) { List<String> ob = null; Stream stream = streamOf(ob); } public static Stream<String> streamOf(List<String> list) { return list == null || list.isEmpty() ? Stream.empty() : list.stream(); } }
© 1996-2017 All Rights Reserved. Stream of Primitives  We can create streams out of three primitive types: int, long and double. In order to allow that, three new special interfaces were created: IntStream, LongStream, DoubleStream.  Each one of these three interfaces include the definition of static methods that generates various streams of the specific primitive type the interface serves .
© 1996-2017 All Rights Reserved. Stream of Primitives IntStream ints = IntStream.range(1, 12); ints.forEach(num->System.out.println(num));
© 1996-2017 All Rights Reserved. Stream of Random Numbers  The Random class has the doubles method that generates randomly generates values of the type double.
© 1996-2017 All Rights Reserved. Stream of Random Numbers Random random = new Random(); DoubleStream stream = random.doubles(10); stream.forEach(num->System.out.println("number="+num));
© 1996-2017 All Rights Reserved. Stream of Chars  Strings can also be used as a source for creating a stream. Using the chars() method of the String class we can get a stream of chars. Since the Java API doesn't have the CharStream, we will use the IntStream instead.
© 1996-2017 All Rights Reserved. Stream of Chars  Strings can also be used as a source for creating a stream. Using the chars() method of the String class we can get a stream of chars. Since the Java API doesn't have the CharStream, we will use the IntStream instead.
© 1996-2017 All Rights Reserved. Stream of Chars IntStream stream = "abc".chars(); stream.forEach((tav->System.out.print((char)tav)));
© 1996-2017 All Rights Reserved. Stream of File  The Files class allows to generate a Stream<String> of a text file using the lines() method. Every line of the text becomes an element of the stream.
© 1996-2017 All Rights Reserved. Stream of File Path path = Paths.get("./file.txt"); Stream<String> stream = Files.lines(path); stream.forEach(str->System.out.println(str));
© 1996-2017 All Rights Reserved. Streams Cannot Be Reused  Once a terminal operation was executed the stream will become inaccessible. It won't be possible to iterate it again.  This behavior makes sense. Streams were designed to provide an ability to apply a finite sequence of operations on a series of elements coming from a specific store. Streams weren't created for storing elements.
© 1996-2017 All Rights Reserved. The forEach() Method  Using this method we can iterate the elements our stream includes.
© 1996-2017 All Rights Reserved. The forEach() Method package com.lifemichael.samples; import java.util.function.*; import java.util.*; import java.util.stream.Stream; public class Program { public static void main(String[] args) { new Random(). ints().limit(10).forEach(System.out::println); } }
© 1996-2017 All Rights Reserved. The forEach() Method
© 1996-2017 All Rights Reserved. The map() Method  Using this method we map each element with a new one calculated based on the first.
© 1996-2017 All Rights Reserved. The map() Method public class Program { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.stream().map(n->n*n). filter(num->num%2==0).distinct(). forEach(System.out::println); } }
© 1996-2017 All Rights Reserved. The map() Method
© 1996-2017 All Rights Reserved. The filter() Method  Using this method we can filter our stream taking out all elements that don't meet our criteria.
© 1996-2017 All Rights Reserved. The filter() Method public class FilterDemo { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.stream(). filter(num->num%2==0). forEach(System.out::println); } }
© 1996-2017 All Rights Reserved. The filter() Method
© 1996-2017 All Rights Reserved. The sorted() Method  Using this method we can sort our stream. There are two versions for this method. The first one sorts the elements in according with their natural order. The second one has a second parameter of the Comparator type.
© 1996-2017 All Rights Reserved. The sorted() Method public class Program { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.add(8); list.stream().sorted(). forEach(System.out::println); } }
© 1996-2017 All Rights Reserved. The sorted() Method
© 1996-2017 All Rights Reserved. Streams Pipeline  In order to perform a sequence of operations over the elements coming from a specific data source and aggregate their results, three parts are needed. The source, the intermediate operation(s) and the terminal operation.  The intermediate operations return a new modified stream.
© 1996-2017 All Rights Reserved. Streams Pipeline  If more than one modification is needed, intermediate operations can be chained with each other.  Only one terminal operation can be used per stream. The forEach method is a terminal operation.
© 1996-2017 All Rights Reserved. Streams Pipeline IntStream ints = IntStream.range(-100, 101); ints.filter(number->number%2==0). filter(number->number>0). filter(number->number%3==0). map(number->2*number). forEach(num->System.out.println(num));
© 1996-2017 All Rights Reserved. Lazy Invocation  The intermediate operations are lazy. They will be invoked only if necessary in order to allow the terminal operation to execute.
© 1996-2017 All Rights Reserved. Lazy Invocation System.out.println("counter="+counter); IntStream ints = IntStream.range(-100, 101); IntStream ints2 = ints.filter(number->number%2==0). filter(number->{ counter++; return number>0; }). filter(number->number%3==0). map(number->2*number); System.out.println("counter="+counter); System.out.println("number of elements is "+ints2.count()); System.out.println("counter="+counter);
© 1996-2017 All Rights Reserved. Lazy Invocation
© 1996-2017 All Rights Reserved. Order of Execution  The right order is one of the most important aspects of chaining operations in the stream pipeline.The intermediate operations that reduce the size of the stream should be placed before the operations that apply each element. Methods, such as filter(), skip() and distinct() better be in the beginning of the chain. This way the performance will improve.
© 2008 Haim Michael 20151026 Questions & Answers Haim Michael 0546655837 Haim.Michael@gmail.com blog.lifemichael.com

Functional programming in Java

  • 1.
    Functional Programming Haim Michael May14th , 2019 All logos, trade marks and brand names used in this presentation belong to the respective owners. lifemichael Java https://youtu.be/6uWjT-lVyZI https://youtu.be/0nMc6nozPzw
  • 2.
    © 1996-2018 AllRights Reserved. Haim Michael Introduction ● Snowboarding. Learning. Coding. Teaching. More than 20 years of Practical Experience. lifemichael
  • 3.
    © 1996-2018 AllRights Reserved. Haim Michael Introduction ● Professional Certifications Zend Certified Engineer in PHP Certified Java Professional Certified Java EE Web Component Developer OMG Certified UML Professional ● MBA (cum laude) from Tel-Aviv University Information Systems Management lifemichael
  • 4.
    © 2008 HaimMichael 20151026 Introduction
  • 5.
    © 2008 HaimMichael 20151026 Introduction  The main programming languages paradigms include the following. Imperative Paradigm The program includes statements executed one by one that change the state. Structured Paradigm Based on Imperative. The code has a more logical structure. Avoiding the goto statement.
  • 6.
    © 2008 HaimMichael 20151026 Introduction Procedural Paradigm Based on Structured. The code is split into procedures been called in order to have a shorted code to maintain. Object Oriented Paradigm During the execution of our code objects are created in order to represent the things our code deals with. Objects are connected with each other. Methods can be invoked on these objects.
  • 7.
    © 2008 HaimMichael 20151026 Introduction Event Driven Paradigm The control flow is determined mainly by the events (e.g. mouse clicks, loading of data ends). Declarative Paradigm The code defines what we want to get without getting into the logic of it nor the details.
  • 8.
    © 2008 HaimMichael 20151026 Functional Programming  Functional programming is a programming paradigm that emphasizes the use of expressions and their evaluation and especially through the definition of functions that are treated as expressions. In addition, it avoids the complexity involved with state changes as the one when using objects and variables.
  • 9.
    © 2008 HaimMichael 20151026 Functional Programming  The use of functions as expressions enable us getting more expressive code. In many cases we will exploit the power of recursion in order to get expressive succinct (expressed in few words) code.
  • 10.
    © 2008 HaimMichael 20151026 Pure Functions
  • 11.
    © 2008 HaimMichael 20151026 Pure Functions  When we define a function that always returns the same value for the very same arguments, and it doesn't depend on any hidden information or state and its evaluation of the result does not cause any observable side effects nor output then it is a pure function.  Pure functions are usually simpler and much easier to test and are very popular in functional programming.
  • 12.
    © 2008 HaimMichael 20151026 Pure Functions  In order to write a pure function we should make sure that we write local only code.  Writing a lambda expression as a pure function is the common approach.
  • 13.
    © 2008 HaimMichael 20151026 Lambda Expressions
  • 14.
    © Haim Michael2017. All Rights Reserved. Introduction  When dealing with an interface that includes one method only and the sole purpose of that interface is to allow us passing over functionality to another part of our program we can use the lambda expression as an alternative for the anonymous inner class.
  • 15.
    © Haim Michael2017. All Rights Reserved. Syntax  The lambda expression includes a comma separated list of formal parameters enclosed within parentheses (the data type of the parameters can be usually omitted). If there is only one parameter then we can omit the parentheses. ob -> ob.age<40
  • 16.
    © Haim Michael2017. All Rights Reserved. Syntax  The body includes a single expression or a statement block. We can include the return statement.
  • 17.
    © Haim Michael2017. All Rights Reserved. Simple Demo package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); } public int calculate(int a, int b, MathOperation op) { return op.execute(a, b); }
  • 18.
    © Haim Michael2017. All Rights Reserved. Simple Demo public static void main(String... args) { SimpleLambdaExpressionDemo myApp = new SimpleLambdaExpressionDemo(); MathOperation addition = (a, b) -> a + b; MathOperation subtraction = (a, b) -> a - b; int num = addition.execute(40, 2); System.out.println("40 + 2 = " + num); System.out.println("20 – 10 = " + myApp.calculate(20, 10, subtraction)); } }
  • 19.
    © Haim Michael2017. All Rights Reserved. Simple Demo The Output
  • 20.
    © Haim Michael2017. All Rights Reserved. Methods References  There are four types of methods references: reference to static method, reference to an instance method of a particular object, reference to an instance method of an arbitrary object of a specific type and reference to constructor.
  • 21.
    © Haim Michael2017. All Rights Reserved. Reference to Static Method  We can refer a static method by specifying the name of the class following with "::" and the name of the static method.
  • 22.
    © Haim Michael2017. All Rights Reserved. Reference to Static Method package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); }
  • 23.
    © Haim Michael2017. All Rights Reserved. Reference to Static Method public static void main(String... args) { MathOperation op = Utils::calcu; int num = op.execute(40, 2); System.out.println("40 * 2 = " + num); } } class Utils { public static int calcu(int a,int b) { return a*b; } }
  • 24.
    © Haim Michael2017. All Rights Reserved. Reference to Static Method The Output
  • 25.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method  We can refer a specific instance method by specifying the reference for the object following with "::" and the name of the instance method.
  • 26.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method package com.lifemichael.samples; public class SimpleLambdaExpressionDemo { interface MathOperation { int execute(int a, int b); }
  • 27.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method public static void main(String... args) { Utils utils = new Utils(); MathOperation op = utils::calcu; int num = op.execute(40, 2); System.out.println("40 * 2 = " + num); } } class Utils { public int calcu(int a,int b) { System.out.println("calcu is called"); return a*b; } }
  • 28.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method The Output
  • 29.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object  We can refer a specific instance method without been specific about the object on which it should be invoked.  Instead of specifying the reference for a specific object we should specify the name of the class followed by :: and the name of the function.
  • 30.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object public class SimpleLambdaExpressionDemo { public static void main(String... args) { Student[] students = { new Student(123123,98,"dave"), new Student(234233,88,"ron"), new Student(452343,82,"ram"), new Student(734344,64,"lara") }; Arrays.sort(students,Student::compareTo); for(Student std : students) { System.out.println(std); } } }
  • 31.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object class Student implements Comparable<Student> { private double average; private int id; private String name; Student(int id, double avg, String name) { this.average = avg; this.id = id; this.name = name; }
  • 32.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object @Override public String toString() { return id+" "+average+" "+name; } @Override public int compareTo(Student o) { if(this.average>o.average) { return 1; } else if(this.average<o.average) { return -1; } else return 0; } }
  • 33.
    © Haim Michael2017. All Rights Reserved. Reference to Instance Method of an Arbitrary Object The Output
  • 34.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor  We can refer the default constructor in a class by writing the name of the class following with ::new.
  • 35.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor public class ReferenceToConstructor { public static void main(String... args) { Student []students = new Student[8]; populate(students, Student::new); for(int i=0; i<students.length; i++) { System.out.println(students[i]); } } public static void populate( Student[] vec, StudentsGenerator ob) { for(int i=0; i<vec.length; i++) { vec[i] = ob.create(); } } }
  • 36.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor interface StudentsGenerator { public Student create(); } class Student implements Comparable<Student> { private static int counter = 1; private static String[] names ={"david","moshe","anat","jake"}; private double average; private int id; private String name; Student() { id = counter++; name = names[(int)(names.length*Math.random())]; average = (int)(100*Math.random()); }
  • 37.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor Student(int id, double avg, String name) { this.average = avg; this.id = id; this.name = name; } @Override public String toString() { return id+" "+average+" "+name; }
  • 38.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor @Override public int compareTo(Student o) { if(this.average>o.average) { return 1; } else if(this.average<o.average) { return -1; } else return 0; } }
  • 39.
    © Haim Michael2017. All Rights Reserved. Reference to Constructor The Output
  • 40.
    © 2008 HaimMichael 20151026 Higher Order Functions
  • 41.
    © 2008 HaimMichael 20151026 Higher Order Functions  When the function we define receives another function (or functions) as an argument(s) or when its returned value is another function it will called an higher order function.
  • 42.
    © 2008 HaimMichael 20151026 Streams
  • 43.
    © 1996-2017 AllRights Reserved. Introduction  Java 8 introduces the possibility to represent a sequence of objects as a stream.  Using streams we can process the sequence of objects in a declarative.
  • 44.
    © 1996-2017 AllRights Reserved. Stream of Collection  The stream() method returns a sequential stream composed of elements coming from a collection.
  • 45.
    © 1996-2017 AllRights Reserved. Stream of Collection package com.lifemichael.samples; import java.util.function.*; import java.util.*; import java.util.stream.Stream; public class Program { public static void main(String[] args) { List<Integer> numbers = new LinkedList<Integer>(); numbers.add(24); numbers.add(13); numbers.add(43); numbers.add(45); numbers.add(12); Stream<Integer> stream = numbers.stream(); stream.filter(num->num%2==0). forEach(num->System.out.println(num)); } }
  • 46.
    © 1996-2017 AllRights Reserved. Stream of Collection
  • 47.
    © 1996-2017 AllRights Reserved. Stream of Array  The stream() method that was defined in the Arrays class allows us to create a stream out of an array we hold.
  • 48.
    © 1996-2017 AllRights Reserved. Stream of Array String[] cities = new String[]{"Rome", "London", "Moscow", "Ashdod", "Haifa", "Eilat", "Zermatt"}; Stream<String> full = Arrays. stream(cities); Stream<String> partial = Arrays. stream(cities, 1, 3); full.forEach(str->System.out.println(str));
  • 49.
    © 1996-2017 AllRights Reserved. Building Streams  Calling the builder static method in Stream we get a Stream.Builder<T> object. Calling builder we should specify the desired type, otherwise we will get a builder for stream of objects.
  • 50.
    © 1996-2017 AllRights Reserved. Building Streams Stream.Builder<String> builder = Stream.<String>builder(); Stream<String> stream = builder. add("london"). add("Paris"). add("Zurich").build(); stream.forEach(str -> System.out.println(str));
  • 51.
    © 1996-2017 AllRights Reserved. Infinite Streams  We can easily create infinite streams. We can do it either using the Stream.generate() or the Stream.iterate() functions.
  • 52.
    © 1996-2017 AllRights Reserved. Infinite Streams  The Stream.generate static method receives a Supplier<T> object, that generates endless number of objects.  If we don't want the Supplier<T> object to work endlessly you better use the limit function in order to limit the size of the generated stream.
  • 53.
    © 1996-2017 AllRights Reserved. Infinite Streams Stream<String> stream = Stream.generate(() -> String. valueOf((int(100*Math.random()))). limit(10); stream.forEach(str -> System.out.println(str));
  • 54.
    © 1996-2017 AllRights Reserved. Infinite Streams  The Stream.iterate static method provides us with an alternative way for creating endless streams. The first argument this method receives is the first element of the stream it is going to generate. The second argument is an UnaryOperator object.
  • 55.
    © 1996-2017 AllRights Reserved. Infinite Streams  If we don't want to get endless stream till the memory ends we better use the limit function in order to limit it.
  • 56.
    © 1996-2017 AllRights Reserved. Infinite Streams Stream<Integer> stream = Stream. iterate(10, n -> n+5). limit(10); stream.forEach(data -> System.out.println(data));
  • 57.
    © 1996-2017 AllRights Reserved. Empty Streams  The empty() method was defined as a static method in Stream.  Calling this method we will get an empty stream. It is a useful method when developing a method that should return a reference for a Stream object. Instead of returning null we can easily return an empty stream.
  • 58.
    © 1996-2017 AllRights Reserved. Empty Streams public class Main { public static void main(String[] args) { List<String> ob = null; Stream stream = streamOf(ob); } public static Stream<String> streamOf(List<String> list) { return list == null || list.isEmpty() ? Stream.empty() : list.stream(); } }
  • 59.
    © 1996-2017 AllRights Reserved. Stream of Primitives  We can create streams out of three primitive types: int, long and double. In order to allow that, three new special interfaces were created: IntStream, LongStream, DoubleStream.  Each one of these three interfaces include the definition of static methods that generates various streams of the specific primitive type the interface serves .
  • 60.
    © 1996-2017 AllRights Reserved. Stream of Primitives IntStream ints = IntStream.range(1, 12); ints.forEach(num->System.out.println(num));
  • 61.
    © 1996-2017 AllRights Reserved. Stream of Random Numbers  The Random class has the doubles method that generates randomly generates values of the type double.
  • 62.
    © 1996-2017 AllRights Reserved. Stream of Random Numbers Random random = new Random(); DoubleStream stream = random.doubles(10); stream.forEach(num->System.out.println("number="+num));
  • 63.
    © 1996-2017 AllRights Reserved. Stream of Chars  Strings can also be used as a source for creating a stream. Using the chars() method of the String class we can get a stream of chars. Since the Java API doesn't have the CharStream, we will use the IntStream instead.
  • 64.
    © 1996-2017 AllRights Reserved. Stream of Chars  Strings can also be used as a source for creating a stream. Using the chars() method of the String class we can get a stream of chars. Since the Java API doesn't have the CharStream, we will use the IntStream instead.
  • 65.
    © 1996-2017 AllRights Reserved. Stream of Chars IntStream stream = "abc".chars(); stream.forEach((tav->System.out.print((char)tav)));
  • 66.
    © 1996-2017 AllRights Reserved. Stream of File  The Files class allows to generate a Stream<String> of a text file using the lines() method. Every line of the text becomes an element of the stream.
  • 67.
    © 1996-2017 AllRights Reserved. Stream of File Path path = Paths.get("./file.txt"); Stream<String> stream = Files.lines(path); stream.forEach(str->System.out.println(str));
  • 68.
    © 1996-2017 AllRights Reserved. Streams Cannot Be Reused  Once a terminal operation was executed the stream will become inaccessible. It won't be possible to iterate it again.  This behavior makes sense. Streams were designed to provide an ability to apply a finite sequence of operations on a series of elements coming from a specific store. Streams weren't created for storing elements.
  • 69.
    © 1996-2017 AllRights Reserved. The forEach() Method  Using this method we can iterate the elements our stream includes.
  • 70.
    © 1996-2017 AllRights Reserved. The forEach() Method package com.lifemichael.samples; import java.util.function.*; import java.util.*; import java.util.stream.Stream; public class Program { public static void main(String[] args) { new Random(). ints().limit(10).forEach(System.out::println); } }
  • 71.
    © 1996-2017 AllRights Reserved. The forEach() Method
  • 72.
    © 1996-2017 AllRights Reserved. The map() Method  Using this method we map each element with a new one calculated based on the first.
  • 73.
    © 1996-2017 AllRights Reserved. The map() Method public class Program { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.stream().map(n->n*n). filter(num->num%2==0).distinct(). forEach(System.out::println); } }
  • 74.
    © 1996-2017 AllRights Reserved. The map() Method
  • 75.
    © 1996-2017 AllRights Reserved. The filter() Method  Using this method we can filter our stream taking out all elements that don't meet our criteria.
  • 76.
    © 1996-2017 AllRights Reserved. The filter() Method public class FilterDemo { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.stream(). filter(num->num%2==0). forEach(System.out::println); } }
  • 77.
    © 1996-2017 AllRights Reserved. The filter() Method
  • 78.
    © 1996-2017 AllRights Reserved. The sorted() Method  Using this method we can sort our stream. There are two versions for this method. The first one sorts the elements in according with their natural order. The second one has a second parameter of the Comparator type.
  • 79.
    © 1996-2017 AllRights Reserved. The sorted() Method public class Program { public static void main(String[] args) { List<Integer> list = new LinkedList(); list.add(12); list.add(54); list.add(53); list.add(65); list.add(72); list.add(8); list.stream().sorted(). forEach(System.out::println); } }
  • 80.
    © 1996-2017 AllRights Reserved. The sorted() Method
  • 81.
    © 1996-2017 AllRights Reserved. Streams Pipeline  In order to perform a sequence of operations over the elements coming from a specific data source and aggregate their results, three parts are needed. The source, the intermediate operation(s) and the terminal operation.  The intermediate operations return a new modified stream.
  • 82.
    © 1996-2017 AllRights Reserved. Streams Pipeline  If more than one modification is needed, intermediate operations can be chained with each other.  Only one terminal operation can be used per stream. The forEach method is a terminal operation.
  • 83.
    © 1996-2017 AllRights Reserved. Streams Pipeline IntStream ints = IntStream.range(-100, 101); ints.filter(number->number%2==0). filter(number->number>0). filter(number->number%3==0). map(number->2*number). forEach(num->System.out.println(num));
  • 84.
    © 1996-2017 AllRights Reserved. Lazy Invocation  The intermediate operations are lazy. They will be invoked only if necessary in order to allow the terminal operation to execute.
  • 85.
    © 1996-2017 AllRights Reserved. Lazy Invocation System.out.println("counter="+counter); IntStream ints = IntStream.range(-100, 101); IntStream ints2 = ints.filter(number->number%2==0). filter(number->{ counter++; return number>0; }). filter(number->number%3==0). map(number->2*number); System.out.println("counter="+counter); System.out.println("number of elements is "+ints2.count()); System.out.println("counter="+counter);
  • 86.
    © 1996-2017 AllRights Reserved. Lazy Invocation
  • 87.
    © 1996-2017 AllRights Reserved. Order of Execution  The right order is one of the most important aspects of chaining operations in the stream pipeline.The intermediate operations that reduce the size of the stream should be placed before the operations that apply each element. Methods, such as filter(), skip() and distinct() better be in the beginning of the chain. This way the performance will improve.
  • 88.
    © 2008 HaimMichael 20151026 Questions & Answers Haim Michael 0546655837 Haim.Michael@gmail.com blog.lifemichael.com