Thursday, January 26, 2017

Concepts in Lamda programming

Usage of Function, Method Reference and Closure in functional programming

package com.java8.chapter3;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Function;
import java.util.function.ToIntFunction;

/* Example of Function<R,T> interface i.e. Converting an object from one DT to another DT
 * Use of Closure in lamda and anonymous inner class
 * Use of Method Reference, replacement of lamda
 * R apply(T t);
*/
public class FunctionLamda {
     public static void main(String[] args) {

List<Integer> list = Arrays.asList(2, 4, 6, 8);
          
// Printing list<Integer>
list.stream().forEach(p -> System.out.println(p));
          
// perform any operation on each element of list and print
System.out.println(performOperation(list,p->p*2));
          
// Create new Integer list(length of String) from list of Strings using  Function<String,Integer>

System.out.println(extractOperation(Arrays.asList("Paras","Suriender","Sham"), s->s.length()));
          
// Create new Integer list(length of String) from list of Strings using ToIntFunction<String>
System.out.println(extractOperation2(Arrays.asList("Paras","Suriender","Sham"), s->s.length()));
    
/* Lamda and annonymous function accessing variables outside of local space
* Closure -a closure is an instance of a function that can reference nonlocal variables of that
function with no restrictions
*/
          
int a=10,b=20;
Thread thread1 = new Thread(new Runnable() {
           public void run() {
           System.out.println(a+b);
     }
     });
thread1.start();
          
Thread thread = new Thread(()-> System.out.println(a));
thread.start();
          
          
Function<String, Integer> stringToInteger =(String s) -> Integer.parseInt(s);
System.out.println(stringToInteger.apply("12346"));
          
// Method Reference , Class :: static method
Function<String, Integer> stringToInteger2 =Integer::parseInt;
System.out.println(stringToInteger2.apply("4123"));
          
}

     public static List<Integer> performOperation(List<Integer> list, Function<Integer, Integer> function) {
           List<Integer> result = new ArrayList<Integer>();
           for(Integer p : list){
                result.add(function.apply(p));
           }
           return result;
     }

     public static List<Integer> extractOperation(List<String> list, Function<String, Integer> function) {
           List<Integer> result = new ArrayList<Integer>();
           for(String p : list){
                result.add(function.apply(p));
           }
           return result;
     }

     public static List<Integer> extractOperation2(List<String> list, ToIntFunction<String> function) {
           List<Integer> result = new ArrayList<Integer>();
           for(String p : list){
                result.add(function.applyAsInt(p));
           }
           return result;
     }
}

Output:

2 4 6 8
[4, 8, 12, 16]
[5, 9, 4]
[5, 9, 4]
30
10
12346
4123


Saturday, January 21, 2017

Passing code with behavior parameterize - Chapter 2

Behavior parameterization is the ability for a method to take multiple different behaviors as parameters and use them internally to accomplish different behaviors.

     · Behavior parameterization lets you make your code more adaptive to changing requirements and saves on engineering efforts in the future.

     · Passing code is a way to give new behaviors as arguments to a method. But it’s verbose prior to Java 8.
     
     ·  Anonymous classes helped a bit before Java 8 to get rid of the verbosity associated with declaring multiple concrete classes for an interface that are needed only once.

     ·  The Java API contains many methods that can be parameterized with different behaviors, which include sorting, threads, and GUI handling.

package com.java8.filteringApple_19Jan17;

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

class Apple {
    private int weight = 0;
    private String color = "";

    public Apple(int weight, String color){
        this.weight = weight;
        this.color = color;
    }

    public Integer getWeight() {
        return weight;
    }

    public void setWeight(Integer weight) {
        this.weight = weight;
    }

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public String toString() {
        return "Apple{" +
               "color='" + color + '\'' +
               ", weight=" + weight +
               '}';
    }
}

interface AppleFormator {
     String accept(Apple a);
}

class FancyAppleFormator implements AppleFormator {
     public String accept(Apple a) {
           String size = a.getWeight() > 150 ? "Heavy" : "Light";
           return "A " + size + " apple of " + a.getColor() + " color";
     }
}

public class PrintApples {
     public static void main(String[] args) {
List<Apple> inventory = Arrays.asList(new Apple(80, "green"), new Apple(155, "black"), new Apple(120,"red"));
          
     /*Below process is verbose because you need to declare multiple classes that you instantiate only once*/
     prettyPrinApple(inventory, new FancyAppleFormator());

           /* Simply passing method implementation as a parameter */
           List<Apple> redApples = filterApples(inventory, p -> p.getColor().equals("red"));
           System.out.println(redApples);

           /* Sorting apples on basis of weight */
           inventory.sort((a1, a2) -> a1.getWeight().compareTo(a2.getWeight()));
           System.out.println("After Sorting inventory based on weight" + inventory);
          
           /* Sorting apples on basis of color */
           inventory.sort((a1,a2)-> a1.getColor().compareTo(a2.getColor()));
           System.out.println("After Sorting inventory based on color" + inventory);
     }

      /* Before Java8 implementation -1
      *  What if we can pass object of class, we could pass behavior of class directly as a parameter
      */
     static void prettyPrinApple(List<Apple> inventory, AppleFormator formattor) {
           for (Apple apple : inventory) {
                System.out.println(formattor.accept(apple));
           }
     }

     /* Using Predicate implementation -2 */
     public static List<Apple> filterApples(List<Apple> inventory, Predicate<Apple> p) {
           List<Apple> result = new ArrayList<>();
           for (Apple apple : inventory) {
                if (p.test(apple)) {
                     result.add(apple);
                }
           }
           return result;
     }
}

Output:

A Light apple of green color
A Heavy apple of black color
A Light apple of red color
[Apple{color='red', weight=120}]
After Sorting inventory based on weight[Apple{color='green', weight=80}, Apple{color='red', weight=120}, Apple{color='black', weight=155}]

After Sorting inventory based on color[Apple{color='black', weight=155}, Apple{color='green', weight=80}, Apple{color='red', weight=120}]