Google

Aug 1, 2014

Java 8 using the Predicate functional interface

The java.util.function package in Java 8 has a number of functional interfaces. Let's look at the Predicate<T> interface that is used for filtering objects from a collection. If you are using a Java version pre Java 8 refer Creating sub lists from a list using predicates to filter.

Here is the Java 8 example:

Step 1: Create a Driver domain class using the builder design pattern. Refer How to create elegant immutable objects in Java for the Driver code.


public class Driver {
 enum SEX {
  MALE, FEMALE
 }

 private String name;
 private int age;
 private SEX sex;

    //builder, and getters,
 
}

If not sure how to apply the builder design pattern to the Driver class.

Step 2: Define a static method to have methods that return Predicates via static methods.

package com.java8.examples;

import java.util.function.Predicate;

public class DriverPredicate {

 public static Predicate<Driver> isEligibleForDriving() {
  return p -> p.getAge() > 18;
 }

 public static Predicate<Driver> isEligibleMaleDriver() {
  return p -> p.getAge() > 18 && p.getSex() == Driver.SEX.MALE;
 }
 
}




Step 3: Create sub lists using the predicates. It is much easier to create sub lists in Java 8.

package com.java8.examples;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DriverTest {

 public static void main(String[] args) {
  List<Driver> drivers = Arrays.asList(
    new Driver.Builder().name("John").age(34).sex(Driver.SEX.MALE).build(),
    new Driver.Builder().name("James").age(24).sex(Driver.SEX.MALE).build(),
    new Driver.Builder().name("Samantha").age(16).sex(Driver.SEX.FEMALE).build()
  );

  
  //using the predicates
  List<Driver> eligibleDriverList = drivers.stream().filter(DriverPredicate.isEligibleForDriving())
    .collect(Collectors.toList());

  List<Driver> eligibleMaleDriverList = drivers.stream().filter(DriverPredicate.isEligibleMaleDriver())
    .collect(Collectors.toList());
  
  System.out.println("eligibleDriverList-->" + eligibleDriverList);
  System.out.println("eligibleMaleDriverList-->" + eligibleMaleDriverList);
  
 }

}


Output:

eligibleDriverList-->[Driver [name=John, age=34, sex=MALE], Driver [name=James, age=24, sex=MALE]]
eligibleMaleDriverList-->[Driver [name=John, age=34, sex=MALE], Driver [name=James, age=24, sex=MALE]]


Optional: You could have written the above trivial code without the DriverPredicate class as shown below. But, in industrial strength applications, you will end up violation the DRY (Don't Repeat Yourself) principle by repeating the filter logic in lambda expressions in multiple places. If the rule changes, you need to modify it in multiple locations.


package com.java8.examples;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

public class DriverTest {

 public static void main(String[] args) {
  List<Driver> drivers = Arrays.asList(
    new Driver.Builder().name("John").age(34).sex(Driver.SEX.MALE).build(),
    new Driver.Builder().name("James").age(24).sex(Driver.SEX.MALE).build(),
    new Driver.Builder().name("Samantha").age(16).sex(Driver.SEX.FEMALE).build()
  );

  
  //using the predicates
  List<Driver> eligibleDriverList = drivers.stream().filter(p -> p.getAge() > 18)
    .collect(Collectors.toList());

  List<Driver> eligibleMaleDriverList = drivers.stream().filter(p -> p.getAge() > 18 && p.getSex() == Driver.SEX.MALE)
    .collect(Collectors.toList());
  
  System.out.println("eligibleDriverList-->" + eligibleDriverList);
  System.out.println("eligibleMaleDriverList-->" + eligibleMaleDriverList);
  
 }

}

Labels: ,

May 27, 2014

Learning to write functional programming with Java 8 with examples -- part 2

In the last post I created custom functional interfaces to explain functional programming, closure, and lambda expressions in Java 8. This post gives Java 8 API examples using lambda expressions and functional programming.

Example 1: The java.lang.Runnable interface has been made a functional interface.


package com.java8.examples;

public class Example1 {
 
 public static void main(String[] args) {
   System.out.println("main thread: " + Thread.currentThread().getName());
   
   //run method takes no arguments so: () -> (body)
   //closure worker thread1
   Runnable r = () -> (System.out.println("worker thread: " + Thread.currentThread().getName())); 
   new Thread(r).start(); //pass the Runnable closure to Thread constructor
   
   //closure worker thread2
   new Thread( () -> (System.out.println("worker thread: " + Thread.currentThread().getName()))).start(); 
 }
}


Output:

main thread: main
worker thread: Thread-0
worker thread: Thread-1


Example 2: The java.util.function package has a number of functional interfaces.

package com.java8.examples;

import java.util.function.Consumer;

public class Example2 {
 
  public static void main(String[] args) {
   //closure of Consumer 1. the accept(T t) method takes Integer here
   Consumer<Integer>  c1 = (x) -> {System.out.println("consumed: " + x);};
   //closure of Consumer 2. x is an Integer  
   Consumer<Integer>  c2 = (x) -> {System.out.println("consumed: " + x*x);};

   
   c1.accept(5);
   c2.accept(5);
   
   //andThen is a default method implementation in Consumer interface
   Consumer<Integer> c3 = c1.andThen(c2);
   c3.accept(6);
 }
}

Output:

consumed: 5
consumed: 25
consumed: 6
consumed: 36


Example 3: The Function&ltT, R> is similar to Consumer<T>, but the Function interface has a return value in its apply(T t) method, whereas the Consumer  has a void method accept(T t).

package com.java8.examples;

import java.util.function.Function;

public class Example3 {
 
  public static void main(String[] args) {
   //closure of Function.  apply(T t) method takes Double here
   Function<Double, Double>  c1 = (arg) -> (arg + arg);
   Function<Double, Double>  c2 = (arg) -> (arg * arg);
  
   Double result1 = c1.apply(5.0);
   Double result2 = c2.apply(5.0);
   
   System.out.println("result1= " + result1);
   System.out.println("result2= " + result2);
   
   //andThen is a default method implementation in Function interface
   Function<Double, Double> c3 = c1.andThen(c2);
   Double result3 = c3.apply(6.0);
   
   System.out.println("result3= " + result3);// 6 + 6 = 12, 12 * 12 = 144;
   
 }
}


Output:

result1= 10.0
result2= 25.0
result3= 144.0


Example 4: The Predicate<T> interface from java.util.function package has test(T t) method that returns a boolean value indicating test condition has passed or failed. The predicates are often used to  filter a collection of objects.

package com.java8.examples;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

public class Example4 {
 
 private static final int SHORT_NAME_LENGTH = 3;
 
 public static void main(String[] args) {
  
  List<String> languages = Arrays.asList("Java", "C++", "PHP", "C#", "Scala", "JRuby", "Jython");
  
  //The Predicate interface has test(T t) that returns a boolean
  Predicate<String> shortNamePredicate = (s) -> (s.length() <= SHORT_NAME_LENGTH); // closure
  
 
  Predicate<String> startsWithCPredicate = (s) -> (s.startsWith("J")); //closure
  
  languages.stream()
           .filter(shortNamePredicate)
           .forEach(e -> System.out.println("short names: " + e));
  
  languages.stream()
           .filter(startsWithCPredicate)
           .forEach(e -> System.out.println("starts with J: " + e));
   
 }
}


Output:

short names: C++
short names: PHP
short names: C#
starts with J: Java
starts with J: JRuby
starts with J: Jython


There are more examples relating working with Java collection -> Understanding Java 8 Streams and working with collections using Lambda expressions

Labels: ,

May 26, 2014

Learning to write functional programming with Java 8 with examples -- part 1

In the earlier post entitled  Understanding Java 8 Lambda expressions with working examples -- part 1, we looked at Summable example to illustrate functional programming. In this tutorial, I will go in more detail with similar examples with scenarios. The example is a a simple arithmetic operation.

Scenario 1:  The Operate interface with the annotation @FunctionalInterface. This annotation ensures that you can only have a single abstract method. You can have additional default and static method implementations.

Step 1: Define the interface. It is an abstract method by default, and  @FunctionalInterface ensures that you can only define a Single Abstract Method (aka SAM).


package com.java8.examples;

@FunctionalInterface
public interface Operation {
    int operate(int operand1, int operand2); 
}

Step 2: The OperationTest class that uses the functional interface with lambda expressions like (x, y) -> (x + y); and  (x, y) -> (x * y) to add and multiply respectively. The method name operate(int operand1, int operand2) is not explictly called as the compiler knows to work it out from the parameters passed int operand1, int operand2 which method to invoke.

package com.java8.examples;

public class OperationTest {

 public static void main(String[] args) {
   OperationTest test = new OperationTest();
   System.out.println("add result = " + test.add(2, 3));
   System.out.println("multiply result = " + test.multiply(2, 3));
 }

 public int add( int input1,  int input2) {
   Operation adder = (x, y) -> (x + y);
   return adder.operate(input1, input2);
 }  
 
 public int multiply( int input1,  int input2) {
   Operation multiplier = (x, y) -> (x * y);
   return multiplier.operate(input1, input2);
 }  
}

Output:

add result = 5
multiply result = 6

The above example will give the same output even without the @FunctionalInterface annotation. You could even have "abstract" in front of  int operate(int operand1, int operand2);

package com.java8.examples;

public interface Operation {
 abstract int operate(int operand1, int operand2);
}



Scenario 2: Have another Operation2 interface that takes 3 integer parameters.


package com.java8.examples;

public interface Operation2 {
 abstract int operate(int operand1, int operand2, int operand3); 
}


The OperationTest class that uses both interfaces. The Operation that take 2 integer parameters and Operation2 that takes 3 integer parameters.

package com.java8.examples;

public class OperationTest {

 public static void main(String[] args) {
   OperationTest test = new OperationTest();
   System.out.println("add result = " + test.add(2, 3));
   System.out.println("multiply result = " + test.multiply(2, 3));
   System.out.println("add 3 numbers result = " + test.add2(2, 3, 4));
 }

 public int add( int input1,  int input2) {
   Operation adder = (x, y)  -> (x + y);
   return adder.operate(input1, input2);
 }  
 
 
 public int multiply( int input1,  int input2) {
   Operation subtracter =  (x, y) -> (x * y);
   return subtracter.operate(input1, input2);
 } 
 
 public int add2( int input1,  int input2, int input3) {
   Operation2 adder = (x, y, z)  -> (x + y + z);
   return adder.operate(input1, input2, input3);
 }  
 
}


Output:

add result = 5
multiply result = 6
add 3 numbers result = 9



Scenario 3: Why do you have default methods in Java 8 interfaces?

This example demonstrates that default methods provide default behaviors, and closures are used to have  special behaviors like add, multiply, divide, subtract, print, etc.

Step 1: Here is the revised Operation interface with default methods.

package com.java8.examples;

import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.Objects;

@FunctionalInterface
public interface Operation<Intetger>  {
 
    //SAM -- Single Abstract Method.
    //identifier abstract is optional
    Integer operate(Integer operand);
 
    default Operation<Integer> add(Integer o){
       return (o1) -> operate(o1) +   o;
    }
 
    default Operation<Integer> multiply(Integer o){
      return (o1) -> operate(o1) * o;
    }
 
    //define other default methods for divide, subtract, etc
 
    default Integer getResult() {
    return operate(0);
    }
    
 default void print(){
  System.out.println("result is = " + getResult());
 }
   
}





Step 2: The revised OperationTest class.

package com.java8.examples;

import static java.lang.System.out;

public class OperationTest {
 
 public static void main(String[] args) {
 
  Operation<Integer> calc = (x) -> (2);
  
  Operation complexOp = calc.add(3)
         .multiply(4)
         .multiply(2)
         .multiply(2)
         .add(4);
  
  complexOp.print();
 
  int result = complexOp.getResult();
 } 
 
}




Output:

result is = 84


We know that Java does not support multiple implementation inheritance to solve the diamond problem (till Java 8). Java did only support multiple interface inheritance. That is, a class can implement multiple interfaces. By having default method implementations in interfaces, you can now have multiple behavioral inheritance in Java 8.  Partially solving the diamond problem.


Scenario 4: Why do you have static methods in Java 8 interfaces?

The static methods are helper methods. Prior to Java 8, the Java APIs used to have separate interfaces and utility methods. For example, Collection interface and Collections utility class, Path interface and Paths utility class, etc.

So, instead of doing Collections.sort(list, ordering), in Java 8 APIs you could do list.sort(ordering);

Secondly, static helper methods are more expressive with meaningful names like plus5, plus10, etc as shown below.

package com.java8.examples;

import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.Objects;

@FunctionalInterface
public interface Operation<Intetger>  {
 
 //SAM -- Single Abstract Method.
 //identifier abstract is optional
 Integer operate(Integer operand);
 
    default Operation<Integer> add(Integer o){
       return (o1) -> operate(o1) +   o;
    }
 
    default Operation<Integer> multiply(Integer o){
      return (o1) -> operate(o1) * o;
    }
 
    //define other default methods for divide, subtract, etc
 
    default Integer getResult() {
    return operate(0);
    }
    
 default void print(){
  System.out.println("result is = " + getResult());
 }
   
 
 //ads 5 to a given number
 static Integer plus5(Integer input) {
  return input + 5 ;
 }
}


Now, how to invoke the static method via Lambda expressions:

package com.java8.examples;

import static java.lang.System.out;

public class OperationTest {
 
 public static void main(String[] args) {
 
  //plus5 is an expressive static helper method that adds 5 to a given number
  Operation<Integer> calc = (x) -> Operation.plus5(2);
  
  Operation complexOp = calc.add(3)
         .multiply(4)
         .multiply(2)
         .multiply(2)
         .add(4);
  
  complexOp.print();
 
  int result = complexOp.getResult();
  
 } 
}


Output:

result is = 164


Learning to write functional programming with Java 8 with examples -- part 2

Labels: ,

Apr 8, 2014

Understanding Java 8 Lambda expressions with working examples -- part 3



Example 4:  Runnable interface and Thread class to create new threads via Lambda expressions

The Java API Runnable interface in Java 8 has been annotated with @FunctionalInterface, which means you can only have 1 abstract method.


@FunctionalInterface
public interface Runnable {
    public abstract void run();
}


public class Thread implements Runnable {
   //..........skipped
}


Step 1: Here is Lambda expression in action to create new threads.

package com.java8.examples;

import java.util.concurrent.atomic.LongAdder;

public class ThreadTest {
 private static LongAdder counter = new LongAdder();

 public static void main(String[] args) {
  
  new Thread(() -> { counter.increment();
                     System.out.println(Thread.currentThread().getName() + " count -- " + counter.longValue());
                   }).start();
  
  Thread t2 = new Thread(() -> { counter.increment();
                     System.out.println(Thread.currentThread().getName() + " count -- " + counter.longValue());
                   });
  t2.start();
  
  
 }
}


The output:
 

Thread-0 count -- 1
Thread-1 count -- 2


Example 5: The free variables in lambda expressions are not thread-safe.

A lambda expression has 3 aspects:

  1. Parameters
  2. A block of code or body
  3. Values for the free variables. These are the variables that are not parameters, and not defined inside the closure.
The anonymous inner classes can only access variables defined outside if they are marked final. Otherwise you will get a compile error. The lambda expression has relaxed the requirement of variables being final, but the "free variables" that you use need to be either final or effectively final.  


package com.java8.examples;

import java.util.concurrent.atomic.LongAdder;

public class ThreadTest {
  private static LongAdder counter = new LongAdder();

  public static void main(String[] args) {
   
   int counterLocal = 0;  //local free variable
     
   
   new Thread(() -> { 
      counter.increment();
               
      //local variables referenced from a lambda expression must be final or effectively final
      counterLocal++; //Line A: illegal. compile-error
                
      System.out.println(counterLocal); // Line B: Ok, as counterLocal is not mutated
      int a = counterLocal; //Line C: Ok, as counterLocal is not mutated
                  
         System.out.println(Thread.currentThread().getName() + " count -- " + counter.longValue());
   }).start();
   
   
   }
}


The above code gives compile error due to Line A. If you comment out Line A, the above code will compile, and Line B and Line C are ok as  they use the variable counterLocal as read only and it is effectively final.

So, mutating free variables in a lambda expression is not thread-safe. The prohibition against mutation only holds true for local variables as explained above. You can still use an instance or static variable, but the compiler won't warn you, but you can have thread-safety issues.


Example 6: Understanding scope of "this" keyword

Will the toString( ) method invocation shown below invokes ThreadTest's toString( ) method or Thread class's toString( ) method?

package com.java8.examples;

import java.util.concurrent.atomic.LongAdder;

public class ThreadTest {

 public static void main(String[] args) {
       new  ThreadTest().execute();
 }
  
 public void execute() {
  new Thread(() -> {
         System.out.println(this.toString());
   }).start();
 }
 
 
 @Override
 public String toString() {
  return "ThreadTest class toString()";
 }
}


Output is:
ThreadTest class toString()

So, there is nothing special about using the "This" keyword in lambda expressions. The scope of lambda expression is nested inside the execute( ) method, and this has the same meaning anywhere inside the execute method.



More on Java 8 functional interfaces and Lambda expressions

Labels: ,

Apr 4, 2014

Understanding Java 8 Lambda expressions with working examples -- part 2

Extends Understanding Java 8 Lambda expressions with working examples -- part 1

Example 3: It is very common to loop through a collection of objects and perform certain tasks like setting a variable, etc. The  Iterable from which the other interfaces like Collection, List, etc has been annotated with @FunctionalInterface.


As shown in the diagram, the  Iterable also has a default  method  forEach(Consumer action)  implemented to loop through the collection.

Step 1: Create a Person POJO object with fields, getters, and setters.

package com.java8.examples;

public class Person {
 
 private String firstName;
 private String surname;
 
 public Person(String firstName) {
  this.firstName = firstName;
 }
 public String getFirstName() {
  return firstName;
 }
 public void setFirstName(String firstName) {
  this.firstName = firstName;
 }
 public String getSurname() {
  return surname;
 }
 public void setSurname(String surname) {
  this.surname = surname;
 }
 
 @Override
 public String toString() {
  return "Person [firstName=" + firstName + ", surname=" + surname + "]";
 }
}



Step 2: Create a collection of  Person objects, and forEach person, set the surname using the Lambda expression and anonymous method call. This is functional programming.

package com.java8.examples;

import java.util.ArrayList;
import java.util.List;

public class PersonCollectionTest {

 public static void main(String[] args) {
  List<Person> persons = new ArrayList<Person>();
  persons.add(new Person("John"));
  persons.add(new Person("Peter"));
  
  // Java 8: Lambda expression that sets surname for each person as "Smith"
  persons.forEach((p) -> {p.setSurname("Smith");});
  
  System.out.println(persons);

 }

}

The output will be

[Person [firstName=John, surname=Smith], Person [firstName=Peter, surname=Smith]]





More on Java 8 functional interfaces and Lambda expressions

Labels: ,

Understanding Java 8 Lambda expressions with working examples -- part 1

The function interfaces and Lambda expressions are going to make your code concise when coding with Java 8.  These are the most awaited features among Java developers. If you understand these 2 examples, you will find the other parts easier to understand.

Q. What is a Lambda expression?
A. Lambda expressions are anonymous methods which are intended to replace the bulkiness of anonymous inner classes with a much more compact mechanism. 

Q. What is a functional interface?
A. The annotation @FunctionalInterface is being introduced. This annotation acts similarly to @Override by signaling to the compiler that the interface is intended to be a functional interface. The compiler will then throw an error if the interface has multiple abstract methods.


Example 1:  writing your own functional interface and Lambda expressions

Step 1: Define  a functional interface Summable with one abstract method as it can only have 1 abstract method. You can declare default and static  methods too.


package com.java8.examples;

@FunctionalInterface
public interface Summable {
  abstract int sum(int input1, int input2);
}


Step 2:  Define the SumTest class and provide the Lambda expression to sum 2 numbers. You can think of it as method implementation of  sum(int input1, int input2) defined in the functional interface above.

package com.java8.examples;

public class SumTest  {

 public static void main(String[] args) {
  System.out.println("Sum = " +  new SumTest().sum(2, 3));
 }

 public int sum( int input1,  int input2) {
  //(argument) -> (body) or
  //(input) -> (result)
  
  Summable adder = (x, y) -> (x + y);

  //invoke anonymous method 
  return adder.sum(input1, input2);
 }  
}

The output will be:

 
Sum = 5



Example 2: Using the existing Java Comparator interface and implementing your own implementation to compare two numbers.

Step 1: Here is the class that implements the compare(T o1, T o2) via anonymous methods using the Lambda expression.

package com.java8.examples;

import java.util.Comparator;

public class CompareTest {

 public static void main(String[] args) {
  System.out.println(new CompareTest().compare(2, 3));
 }

 public int compare( int input1,  int input2) {
  //(argument) -> (body)
  //(input) -> (result)
  
  Comparator<Integer> cmp = (x, y) -> {
       return (x < y) ? -1 : ((x > y) ? 1 : 0);
  };
  
  //invoke anonymous method
  return cmp.compare(input1, input2);
    
 }
}

The output:
 
-1



Step: optional understanding: To understand this better, if you inspect the Comparator interface, it has been enhanced in Java 8 with

  •  @FunctionalInterface annotation
  • a number of default method implementations like reversed( ), thenComparing(Comparator other), etc.
  • a number of static utility methods like naturalOrder ( ), nullsLast(Comparator comparator), etc.


The simplified Comparator functional interface looks like

 
package java.util;

import java.io.Serializable;
import java.util.function.Function;
import java.util.function.ToIntFunction;
import java.util.function.ToLongFunction;
import java.util.function.ToDoubleFunction;
import java.util.Comparators;

@FunctionalInterface
public interface Comparator<T> {

     int compare(T o1, T o2);
     boolean equals(Object obj);

  default Comparator<T> reversed() {
       return Collections.reverseOrder(this);
    }
 
    //...skipping some methods
 
 public static <T> Comparator<T> nullsLast(Comparator<? super T> comparator) {
        return new Comparators.NullComparator<>(false, comparator);
    }

}


More on Java 8 functional interfaces and Lambda expressions

Labels: ,