Favor Functional Over Imperative Style

 class​ Inventory {
 
  List<Supply> supplies = ​new​ ArrayList<>();
 
 long​ countDifferentKinds() {
» List<String> names = ​new​ ArrayList<>();
 for​ (Supply supply : supplies) {
 if​ (supply.isUncontaminated()) {
  String name = supply.getName();
 if​ (!names.contains(name)) {
  names.add(name);
  }
  }
  }
 return​ names.size();
  }
 }

When it comes to working with collections, a functional programming style can be much more readable than its imperative sibling.

Above, you can see a short but relatively complex method that does some very common things: it iterates over a collection and does a few conditional computations. Even though the code’s short and named properly, you need a moment to understand what it’s doing.

The code is imperative in style. It tells the computer what to do and how to do it through loops, conditionals, assignments of variables, and method calls. And the machine will simply follow that recipe line by line. You can look over its shoulder with a debugger.

But usually, we’re most interested in what the code does and not so much in how it reaches its goal. That’s why we invest so much effort in writing good comments and choosing good names.

Here, the code clouds the intent of the method through its size and the amount of text that we have to read line by line. With lambda expressions, we have the option to specify only what we want to get done, without caring about the how. That makes for more concise and readable code.

So how can we clarify the code with lambdas?

 class​ Inventory {
 
  List<Supply> supplies = ​new​ ArrayList<>();
 
 long​ countDifferentKinds() {
»return​ supplies.stream()
  .filter(supply -> supply.isUncontaminated())
  .map(supply -> supply.getName())
  .distinct()
  .count();
  }
 }

Astonishing, isn’t it? Instead of coding the how, we just stated the what, and this makes it so much shorter and more readable. But let’s dissect the code line by line.

First, we enter the collection stream(). That’s the starting operator, which converts the collection into a stream and opens up the world of functional programming to us! Think of starting a boat rally on a river—each element in the collection is a boat (or use the Collection Pipeline Metaphor[44]).

Second, we filter() out any supplies that are contaminated. A filter is like a gate that allows through only boats that fulfill a condition. Here, the filter only allows uncontaminated supplies to continue their journey. Type-wise, a filter is a Predicate that evaluates something to either true or false—the signature of the single abstract method is boolean test(Supply supply) for this instance.

Third, we transform (or map) our “boats” on the river. You can think of modifying a boat’s cargo. In this case, we take out a part of the Supply, its name, and throw the rest overboard. In Java terms, a Function maps a type (Supply) to another one (String).

Fourth, we do more filtering with distinct(): a name is let through only once; any duplicates are discarded.

Finally, we count() the remaining elements in the stream. This is a termination operator that ends the stream and brings us back into the imperative style.

That’s still just the surface of what you can do with collections and lambda expressions. The JavaDoc of the java.util.stream package[45] already contains a nicely written guide to the stream API. For a more comprehensive introduction, Functional Programming in Java [Sub14] is an excellent reference.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.221.254.61