Sunday, 28 September 2014

Using immutability in Java to support functional programming and avoid side effects

The following article is based on Venkat Subramaniam's article "Programming with immutability in Java" in "The Developer" magazine No. 3 2013. The code presented below shows how Java 8 supports immutability with different techniques. Consider the following Java 8 code sample:

import java.util.*;
import java.util.stream.*;

public class ImmutableTest1 {

 public static void printTotal(Stream<Integer> values){
  long start = System.nanoTime(); 
  final int total = 
   values
   .filter(value->value>3)
   .filter(value->isEven(value))
   .mapToInt(value->value*2)
   .sum(); 

   long end = System.nanoTime(); 
   System.out.printf("Total: %d Time: %.3f seconds\n", total, (end - start)/1.0e9); 

 }

 public static boolean isEven(int number){
  try {
   Thread.sleep(100); 
  }
  catch (Exception ex){   
   System.out.println(ex.getMessage());
  }
  return number % 2 == 0; 
 }

 public static void main(String[] args){
  List<Integer>values = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
  printTotal(values.stream());
  printTotal(values.parallelStream());
  
  for (int element : values) {
   Runnable runnable = () -> System.out.println(element);
   runnable.run();
  }
  
  List<String> namesList = Arrays.asList("Jake", "Raju", "Kim", "Kara", "Paul", "Brad", "Mike"); 
  System.out.println("Found a 3 letter name?: " + 
    namesList.stream().anyMatch(name->name.length() == 3)); 
  
  System.out.println("Found Kim?: " + 
    namesList.stream().anyMatch(name-> name.contains("Kim")));
 }

}

The code above shows how library functions in the Stream API of Java 8 avoids the use of mutable variables by the functional programming code style of chaining. Further, note that the use of a classical for loop prohibits the loop creating new Runnable instances, while the for loop over a collection allows this. The error given for classical for loop is: Local variable i defined in an enclosing scope must be final or effectively final ImmutableTest1.java /ImmutabilityTest1/src line 36 Java Problem given this code:
 for (int i = 0; i < values.size(); i++) {
   Runnable runnable = () -> System.out.println(values.get(i));
   runnable.run();
        }
In addition, recursion is a technique that provides immutability to your code, by avoiding use of mutable control variables, example follows:

import java.util.Scanner;


public class Guesser {
 
 final static int target = (int) (Math.random() * 100); 
 
 public static void play(final int attempts){
  System.out.print("Enter your guess:");
  final int guess = new Scanner(System.in).nextInt();
  if (guess < target)
   System.out.println("Aim higher"); 
  if (guess > target)
   System.out.println("Aim lower");
  
  if (guess == target)
   System.out.printf("You got it in %d attempts\n", attempts);
  else 
   play(attempts+1);
  
 }
 
 public static void main(String[] args){
  System.out.println("I've selected a number, can you guess?"); 
  play(1);
 }

}


No comments:

Post a Comment