Exceptional Handling in Lambda expressions- Functional Programming in JAVA 8- Part 6

Java

Before reading this post kindly go from part 1 of this post to understand lambda expression.

http://jkoder.com/understanding-java-8-lambda-expression-functional-programming-in-java-8-part-1/

Lambda expressions are typically inline implementation of interfaces. It basically deals with the computation part, and we all know that in real world nothing is ideal. So, we may get exceptions in our code, and lambdas are no free from exceptions. So, in this post we will have a look at a strategy of catching exceptions. We will create a lambda expression which takes in an array of integers, and a key integer, and do mathematical operations on the integer array for a given key.

public class ExceptionHandlingExample {

	public static void main(String[] args) {
		int [] someNumbers={1,2,3,4};
		int key=2;
		
		process(someNumbers, key);
	}

	private static void process(int[] someNumbers, int key) {
		for(int i: someNumbers){
			System.out.println(i+key);
		}
	}
}

In the above code we are adding integer 2 to each and every integer of someNumbers array. Now let’s introduce lambda expression into above code. We will perform System.out.println(i+key) in a lambda expression.

public class ExceptionHandlingExample {

	public static void main(String[] args) {
		int [] someNumbers={1,2,3,4};
		int key=2;
		
		process(someNumbers, key, (v, k)->System.out.println(v+k));
	}

	private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
		for(int i: someNumbers){
			consumer.accept(i, key);
		}
	}
}

We have used accept method of BiConsumer in-built interface of java.util.function package, which takes in 2 objects and returns void.

Now we will write another lambda expression for division.

public class ExceptionHandlingExample {

	public static void main(String[] args) {
		int [] someNumbers={1,2,3,4};
		int key=2;
		
		process(someNumbers, key, (v, k)->System.out.println(v+k));
                process(someNumbers, key, (v, k)->System.out.println(v/k));
	}

	private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
		for(int i: someNumbers){
			consumer.accept(i, key);
		}
	}
}

Now what if integer key=0. So, here we do expect ArithmeticException here, now how to handle it. One way is to wrap try-catch around accept method.

public class ExceptionHandlingExample {

	public static void main(String[] args) {
		int [] someNumbers={1,2,3,4};
		int key=2;
		
                process(someNumbers, key, (v, k)->System.out.println(v+k));
		process(someNumbers, key, (v, k)->System.out.println(v/k));
	}

	private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
		for(int i: someNumbers){
                        try{
			   consumer.accept(i, key);
                        }catch(ArithmeticException e){
                            System.out.println("ArithmeticException occurred");
                        }
		}
	}
}

Works OK, but here the exceptional handling is generalized. So, if our lambda expression is of addition or division, this exception handling will be applied to both of them. However the exception handling makes sense when it is division. So, let’s rewrite above for division.

public class ExceptionHandlingExample {

	public static void main(String[] args) {
		int [] someNumbers={1,2,3,4};
		int key=2;
		
		process(someNumbers, key, (v, k)->System.out.println(v+k));
                process(someNumbers, key, (k, v)->{
			try{	
			       System.out.println(k/v);
			}catch(ArithmeticException e){
				System.out.println("Arithmetic Exception");
			}
		});
	}

	private static void process(int[] someNumbers, int key, BiConsumer<Integer, Integer> consumer) {
		for(int i: someNumbers){
			consumer.accept(i, key);
		}
	}
}

Now this looks meaningful.

About Anoop Kumar Rai