12 October 2016

Using Java 8 Optional and reduce null checking


I am a big fan with the new streams API of Java 8, and I hope it would be used every where in the language.

For example, I hope that, Instead of CompletableFuture interface has  a method named thenApply I hope the name would be "map" instead. and for method like thenAccept, I hope the name would be "forEach" instead.

The point is, thenApply method in the CompleteableFuture interface is more or less a mapping operation, that takes the output of the step before it as input and generates a new output.

Also, theAccept is kind of consumer operation, like forEach, which will will take the output of the previous step as an input and consumes it without generating any output.

And if we talk about the Optional object in Java 8, although I don't have much more functional operations, but he have good enough to allow us to use it to reduce null checking.

The Optional Object has a map and filter (besides its regular methods such as orElseXXX methods).

Here's One example of its usage:

Suppose we have this Object structure that returned from some webservice:

                  static class Result {
Departement departement;
}


static class Departement{
List<Employee> employees;
}


static class Employee{
String name;
}

Then suppose our webservice return the result as one of these 4 functions:

       static Result simulateWsResult1() {
Employee e1 = new Employee();
e1.name = "Ali";
Employee e2 = new Employee();
e2.name = "Muhammad";


Departement dept = new Departement();
dept.employees = Arrays.asList(e1, e2);

Result result = new Result();
result.departement = dept;

return result;
}

static Result simulateWsResult2() {
Employee e1 = new Employee();
Employee e2 = new Employee();

Departement dept = new Departement();
dept.employees = Arrays.asList(e1, e2);

Result result = new Result();
result.departement = dept;

return result;
}

static Result simulateWsResult3() {
Departement dept = new Departement();

Result result = new Result();
result.departement = dept;

return result;
}

static Result simulateWsResult4() {
Result result = new Result();

return result;
}

Then, the main method looks like:

       public static void main(String[] args) {

System.out.println(getEmployeeNames(simulateWsResult1()));
System.out.println(getEmployeeNames(simulateWsResult2()));
System.out.println(getEmployeeNames(simulateWsResult3()));
System.out.println(getEmployeeNames(simulateWsResult4()));
}

And here's the parsing method: getEmployeeNames

       static List<String> getEmployeeNames(Result r){

return
Optional.ofNullable(r)
.map(result -> result.departement)
.map(dept -> dept.employees)
.map(empList -> empList.stream())
.map(empStream -> empStream.filter(e -> e.name != null).map(e -> e.name))
.orElse(Stream.empty())
.collect(Collectors.toList());
}

Complete code here.

Thanks.

No comments: