Intermediate Methods

Intermediate Methods ”; Previous Next Stream API was introduced in Java 8 to facilitate functional programming in Java. A Stream API is targeted towards processing of collections of objects in functional way. By definition, a Stream is a Java component which can do internal iteration of its elements. A Stream interface has terminal as well as non-terminal methods. Non-terminal methods are such operations which adds a listener to a stream. When a terminal method of stream is invoked, then internal iteration of stream elements get started and listener(s) attached to stream are getting called for each element and result is collected by the terminal method. Such non-terminal methods are called Intermediate methods. The Intermediate method can only be invoked by called a terminal method. Following are some of the important Intermediate methods of Stream interface. filter − Filters out non-required elements from a stream based on given criteria. This method accepts a predicate and apply it on each element. If predicate function return true, element is included in returned stream. map − Maps each element of a stream to another item based on given criteria. This method accepts a function and apply it on each element. For example, to convert each String element in a stream to upper-case String element. flatMap − This method can be used to maps each element of a stream to multiple items based on given criteria. This method is used when a complex object needs to be broken into simple objects. For example, to convert list of sentences to list of words. distinct − Returns a stream of unique elements if duplicates are present. limit − Returns a stream of limited elements where limit is specified by passing a number to limit method. Example – Intermediate Methods import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class FunctionTester { public static void main(String[] args) { List<String> stringList = Arrays.asList(“One”, “Two”, “Three”, “Four”, “Five”, “One”); System.out.println(“Example – Filtern”); //Filter strings whose length are greater than 3. Stream<String> longStrings = stringList .stream() .filter( s -> {return s.length() > 3; }); //print strings longStrings.forEach(System.out::println); System.out.println(“nExample – Mapn”); //map strings to UPPER case and print stringList .stream() .map( s -> s.toUpperCase()) .forEach(System.out::println); List<String> sentenceList = Arrays.asList(“I am Mahesh.”, “I love Java 8 Streams.”); System.out.println(“nExample – flatMapn”); //map strings to UPPER case and print sentenceList .stream() .flatMap( s -> { return (Stream<String>) Arrays.asList(s.split(” “)).stream(); }) .forEach(System.out::println); System.out.println(“nExample – distinctn”); //map strings to UPPER case and print stringList .stream() .distinct() .forEach(System.out::println); System.out.println(“nExample – limitn”); //map strings to UPPER case and print stringList .stream() .limit(2) .forEach(System.out::println); } } Output Example – Filter Three Four Five Example – Map ONE TWO THREE FOUR FIVE ONE Example – flatMap I am Mahesh. I love Java 8 Streams. Example – distinct One Two Three Four Five Example – limit One Two Print Page Previous Next Advertisements ”;

Fixed Length Streams

Functional Programming – Fixed length Streams ”; Previous Next There are multiple ways using which we can create fix length streams. Using Stream.of() method Using Collection.stream() method Using Stream.builder() method Following example shows all of the above ways to create a fix length stream. Example – Fix Length Stream import java.util.Arrays; import java.util.List; import java.util.stream.Stream; public class FunctionTester { public static void main(String[] args) { System.out.println(“Stream.of():”); Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5); stream.forEach(System.out::println); System.out.println(“Collection.stream():”); Integer[] numbers = {1, 2, 3, 4, 5}; List<Integer> list = Arrays.asList(numbers); list.stream().forEach(System.out::println); System.out.println(“StreamBuilder.build():”); Stream.Builder<Integer> streamBuilder = Stream.builder(); streamBuilder.accept(1); streamBuilder.accept(2); streamBuilder.accept(3); streamBuilder.accept(4); streamBuilder.accept(5); streamBuilder.build().forEach(System.out::println); } } Output Stream.of(): 1 2 3 4 5 Collection.stream(): 1 2 3 4 5 StreamBuilder.build(): 1 2 3 4 5 Print Page Previous Next Advertisements ”;

High Order Functions

Functional Programming – High Order Functions ”; Previous Next A function is considered as a High Order function if it fulfils any one of the following conditions. It takes one or more parameters as functions. It returns a function after its execution. Java 8 Collections.sort() method is an ideal example of a high order function. It accepts a comparing method as an argument. See the example below − import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.List; import java.util.stream.Collectors; public class FunctionTester { public static void main(String[] args) { List<Integer> numbers = Arrays.asList(3, 4, 6, 7, 9); //Passing a function as lambda expression Collections.sort(numbers, (a,b) ->{ return a.compareTo(b); }); System.out.println(numbers); Comparator<Integer> comparator = (a,b) ->{ return a.compareTo(b); }; Comparator<Integer> reverseComparator = comparator.reversed(); //Passing a function Collections.sort(numbers, reverseComparator); System.out.println(numbers); } } Output [3, 4, 6, 7, 9] [9, 7, 6, 4, 3] Print Page Previous Next Advertisements ”;

Returning a Function

Functional Programming – Returning a Function ”; Previous Next As a High Order function can return a function but how to implement using Java 8. Java 8 has provided Function interface which can accept a lambda expression. A high order function can return a lamdba expression and thus this high order function can be used to create any number of functions. See the example below − import java.util.function.Function; public class FunctionTester { public static void main(String[] args) { Function<Integer, Integer> addOne = adder(1); Function<Integer, Integer> addTwo = adder(2); Function<Integer, Integer> addThree = adder(3); //result = 4 + 1 = 5 Integer result = addOne.apply(4); System.out.println(result); //result = 4 + 2 = 6 result = addTwo.apply(4); System.out.println(result); //result = 4 + 3 = 7 result = addThree.apply(4); System.out.println(result); } //adder – High Order Function //returns a function as lambda expression static Function<Integer, Integer> adder(Integer x){ return y -> y + x; } } Output 5 6 7 Print Page Previous Next Advertisements ”;

Constructor References

Constructor References ”; Previous Next Constructor references help to point to Constructor method. A Constructor reference is accessed using “::new” symbol. //Constructor reference Factory vehicle_factory = Vehicle::new; Following example shows how Constructor references works in Java 8 onwards. interface Factory { Vehicle prepare(String make, String model, int year); } class Vehicle { private String make; private String model; private int year; Vehicle(String make, String model, int year){ this.make = make; this.model = model; this.year = year; } public String toString(){ return “Vehicle[” + make +”, ” + model + “, ” + year+ “]”; } } public class FunctionTester { static Vehicle factory(Factory factoryObj, String make, String model, int year){ return factoryObj.prepare(make, model, year); } public static void main(String[] args) { //Constructor reference Factory vehicle_factory = Vehicle::new; Vehicle carHonda = factory(vehicle_factory, “Honda”, “Civic”, 2017); System.out.println(carHonda); } } Output Vehicle[Honda, Civic, 2017] Print Page Previous Next Advertisements ”;

Type Inference

Functional Programming – Type Inference ”; Previous Next Type inference is a technique by which a compiler automatically deduces the type of a parameter passed or of return type of a method. Java 8 onwards, Lambda expression uses type inference prominently. See the example below for clarification on type inference. Example- Type Inference public class FunctionTester { public static void main(String[] args) { Join<Integer,Integer,Integer> sum = (a,b) -> a + b; System.out.println(sum.compute(10,20)); Join<String, String, String> concat = (a,b) -> a + b; System.out.println(concat.compute(“Hello “,”World!”)); } interface Join<K,V,R>{ R compute(K k ,V v); } } Output 30 Hello World! A lambda expression treats each parameter and its return type as Object initially and then inferred the data type accordingly. In first case, the type inferred is Integer and in second case type inferred is String. Print Page Previous Next Advertisements ”;

Currying

Functional Programming with Java – Currying ”; Previous Next Currying is a technique where a many arguments function call is replaced with multiple method calls with lesser arguments. See the below equation. (1 + 2 + 3) = 1 + (2 + 3) = 1 + 5 = 6 In terms of functions: f(1,2,3) = g(1) + h(2 + 3) = 1 + 5 = 6 This cascading of functions is called currying and calls to cascaded functions must gives the same result as by calling the main function. Following example shows how Currying works. import java.util.function.Function; public class FunctionTester { public static void main(String[] args) { Function<Integer, Function<Integer, Function<Integer, Integer>>> addNumbers = u -> v -> w -> u + v + w; int result = addNumbers.apply(2).apply(3).apply(4); System.out.println(result); } } Output 9 Print Page Previous Next Advertisements ”;

Functional Interfaces

Functional Programming – Functional Interfaces ”; Previous Next Functional interfaces have a single functionality to exhibit. For example, a Comparable interface with a single method ”compareTo” is used for comparison purpose. Java 8 has defined a lot of functional interfaces to be used extensively in lambda expressions. Following is the list of functional interfaces defined in java.util.Function package. Given below is the list of interfaces in Java8. Sr.No. Interface & Description 1 BiConsumer<T,U> Represents an operation that accepts two input arguments, and returns no result. 2 BiFunction<T,U,R> Represents a function that accepts two arguments and produces a result. 3 BinaryOperator<T> Represents an operation upon two operands of the same type, producing a result of the same type as the operands. 4 BiPredicate<T,U> Represents a predicate (Boolean-valued function) of two arguments. 5 BooleanSupplier Represents a supplier of Boolean-valued results. 6 Consumer<T> Represents an operation that accepts a single input argument and returns no result. 7 DoubleBinaryOperator Represents an operation upon two double-valued operands and producing a double-valued result. 8 DoubleConsumer Represents an operation that accepts a single double-valued argument and returns no result. 9 DoubleFunction<R> Represents a function that accepts a double-valued argument and produces a result. 10 DoublePredicate Represents a predicate (Boolean-valued function) of one double-valued argument. 11 DoubleSupplier Represents a supplier of double-valued results. 12 DoubleToIntFunction Represents a function that accepts a double-valued argument and produces an int-valued result. 13 DoubleToLongFunction Represents a function that accepts a double-valued argument and produces a long-valued result. 14 DoubleUnaryOperator Represents an operation on a single double-valued operand that produces a double-valued result. 15 Function<T,R> Represents a function that accepts one argument and produces a result. 16 IntBinaryOperator Represents an operation upon two int-valued operands and produces an int-valued result. 17 IntConsumer Represents an operation that accepts a single int-valued argument and returns no result. 18 IntFunction<R> Represents a function that accepts an int-valued argument and produces a result. 19 IntPredicate Represents a predicate (Boolean-valued function) of one int-valued argument. 20 IntSupplier Represents a supplier of int-valued results. 21 IntToDoubleFunction Represents a function that accepts an int-valued argument and produces a double-valued result. 22 IntToLongFunction Represents a function that accepts an int-valued argument and produces a long-valued result. 23 IntUnaryOperator Represents an operation on a single int-valued operand that produces an int-valued result. 24 LongBinaryOperator Represents an operation upon two long-valued operands and produces a long-valued result. 25 LongConsumer Represents an operation that accepts a single long-valued argument and returns no result. 26 LongFunction<R> Represents a function that accepts a long-valued argument and produces a result. 27 LongPredicate Represents a predicate (Boolean-valued function) of one long-valued argument. 28 LongSupplier Represents a supplier of long-valued results. 29 LongToDoubleFunction Represents a function that accepts a long-valued argument and produces a double-valued result. 30 LongToIntFunction Represents a function that accepts a long-valued argument and produces an int-valued result. 31 LongUnaryOperator Represents an operation on a single long-valued operand that produces a long-valued result. 32 ObjDoubleConsumer<T> Represents an operation that accepts an object-valued and a double-valued argument, and returns no result. 33 ObjIntConsumer<T> Represents an operation that accepts an object-valued and an int-valued argument, and returns no result. 34 ObjLongConsumer<T> Represents an operation that accepts an object-valued and a long-valued argument, and returns no result. 35 Predicate<T> Represents a predicate (Boolean-valued function) of one argument. 36 Supplier<T> Represents a supplier of results. 37 ToDoubleBiFunction<T,U> Represents a function that accepts two arguments and produces a double-valued result. 38 ToDoubleFunction<T> Represents a function that produces a double-valued result. 39 ToIntBiFunction<T,U> Represents a function that accepts two arguments and produces an int-valued result. 40 ToIntFunction<T> Represents a function that produces an int-valued result. 41 ToLongBiFunction<T,U> Represents a function that accepts two arguments and produces a long-valued result. 42 ToLongFunction<T> Represents a function that produces a long-valued result. 43 UnaryOperator<T> Represents an operation on a single operand that produces a result of the same type as its operand. Functional Interface Example Predicate <T> interface is a functional interface with a method test(Object) to return a Boolean value. This interface signifies that an object is tested to be true or false. Create the following Java program using any editor of your choice in, say, C:> JAVA. Java8Tester.java import java.util.Arrays; import java.util.List; import java.util.function.Predicate; public class Java8Tester { public static void main(String args[]) { List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); // Predicate<Integer> predicate = n -> true // n is passed as parameter to test method of Predicate interface // test method will always return true no matter what value n has. System.out.println(“Print all numbers:”); //pass n as parameter eval(list, n->true); // Predicate<Integer> predicate1 = n -> n%2 == 0 // n is passed as parameter to test method of Predicate interface // test method will return true if n%2 comes to be zero System.out.println(“Print even numbers:”); eval(list, n-> n%2 == 0 ); // Predicate<Integer> predicate2 = n -> n > 3 // n is passed as parameter to test method of Predicate interface // test method will return true if n is greater than 3. System.out.println(“Print numbers greater than 3:”); eval(list, n-> n > 3 ); } public static void eval(List<Integer> list, Predicate<Integer> predicate) { for(Integer n: list) { if(predicate.test(n)) { System.out.println(n + ” “); } } } } Here we”ve passed Predicate interface, which takes a single input and returns Boolean. Verify the Result Compile the class using javac compiler as follows − C:JAVA>javac Java8Tester.java Now run the Java8Tester as follows − C:JAVA>java Java8Tester It should produce the following output − Print all numbers: 1 2 3 4 5 6 7 8 9 Print even numbers: 2 4 6 8 Print numbers greater than 3: 4 5 6 7 8 9 Print Page Previous Next Advertisements ”;

Home

Functional Programming with Java Tutorial PDF Version Quick Guide Resources Job Search Discussion From Java 8 onwards, many functional programming elements are introduced like lambda expression, functional interfaces in Java. These elements are to ease functional programming in Java which was originally a imperative and Object Oriented language. Audience This tutorial is designed for Software Professionals who are willing to learn Functional Programming using Java in simple and easy steps. This tutorial will give you an understanding of the Functional Programming concepts and after completing this tutorial you will be at an intermediate level of expertise from where you can take yourself to a higher level of expertise. Prerequisites Before proceeding with this tutorial, you should have a basic understanding of Java, and execution of programs, etc. Print Page Previous Next Advertisements ”;

Recursion

Functional Programming with Java – Recursion ”; Previous Next Recursion is calling a same function in a function until certain condition are met. It helps in breaking big problem into smaller ones. Recursion also makes code more readable and expressive. Imperative vs Recursive Following examples shows the calculation of sum of natural numbers using both the techniques. public class FunctionTester { public static void main(String[] args) { System.out.println(“Sum using imperative way. Sum(5) : ” + sum(5)); System.out.println(“Sum using recursive way. Sum(5) : ” + sumRecursive(5)); } private static int sum(int n){ int result = 0; for(int i = 1; i <= n; i++){ result = result + i; } return result; } private static int sumRecursive(int n){ if(n == 1){ return 1; }else{ return n + sumRecursive(n-1); } } } Output Sum using imperative way. Sum(5) : 15 Sum using recursive way. Sum(5) : 15 Using recursion, we are adding the result of sum of n-1 natural numbers with n to get the required result. Tail Recursion Tail recursion says that recursive method call should be at the end. Following examples shows the printing of a number series using tail recursion. public class FunctionTester { public static void main(String[] args) { printUsingTailRecursion(5); } public static void printUsingTailRecursion(int n){ if(n == 0) return; else System.out.println(n); printUsingTailRecursion(n-1); } } Output 5 4 3 2 1 Head Recursion Head recursion says that recursive method call should be in the beginning of the code. Following examples shows the printing of a number series using head recursion. public class FunctionTester { public static void main(String[] args) { printUsingHeadRecursion(5); } public static void printUsingHeadRecursion(int n){ if(n == 0) return; else printUsingHeadRecursion(n-1); System.out.println(n); } } Output 1 2 3 4 5 Print Page Previous Next Advertisements ”;