Konrad Reiche About Photos Talks

Traversing your collections functional

Since most of the Java code I wrote in the past was on Android I was not able to enjoy too many Java 8 features yet. Though recently I wrote a microservice in Java using Spring Boot where I could make full use of lambdas and functional interfaces. The following method, for instance, returns the sum of all transactions for a specified instance by traversing their children.

@RequestMapping(value = "/transaction/sum/{id}", method = RequestMethod.GET)
BigDecimal Sum sum(@PathVariable long id) {
    List<Transaction> transactions = new ArrayList<>();
    Transaction current = repository.find(id);

    while (current != null) {
        transactions.add(current);
        current = current.getChild();
    }

    return transactions.stream().map(t -> t.getAmount())
            .reduce(BigDecimal.ZERO, BigDecimal::add);
}

As someone who learned Haskell in his freshman year I cannot but love the simplicity. Also, because it is a very common way to express this statement in Ruby. The code above the return statement could not be more imperative and I was wondering whether there is a way to express this in a functional way, too. In Ruby we could possible implement it like this:

sum = lambda { |t| t ? t.amount + sum.call(t.child) : 0 }
sum.call(t1).reduce(&:+)

Here summation and iteration are combined. An obvious drawback is that the lambda here is limited to the stack size. Alternatively, we could use the Enumerable method inject on the transaction instance:

t1.inject(0) { |sum, t| sum + t1.amount }

This, however, would only work if we implement the Enumerable interface in Ruby by defining each.

class Transaction
  include Enumerable

  def each
    yield self
    yield child if child
  end
end

Back to Java. Can we achieve something similar? Another Java 8 addition is the Spliterator interface.

An object for traversing and partitioning elements of a source. The source of elements covered by a Spliterator could be, for example, an array, a Collection, an IO channel, or a generator function.

The splittable iterator is especially handy when you want to split off parts of the collections for instance to utilize parallel processing. The necessary method in this case is the forEachRemaining.

public class Transaction implements Spliterator<Transaction> {

  @Override
  public void forEachRemaining(Consumer<? super Transaction> action) {
    Transaction current = this;
      while (current != null) {
        action.accept(current);
        current = current.getChild();
      }
  }

}

Finally, we can reduce the REST service method to the following three lines of code:

@RequestMapping(value = "/sum/{id}", method = RequestMethod.GET)
long sum(@PathVariable Long id) {
    Transaction current = repository.find(id);
    Stream<Transaction> stream =  StreamSupport.stream(current, false);
    return stream.map(t -> t.getAmount()).reduce(BigDecimal.ZERO, BigDecimal::add);
}

Personally, I find this very satisfying – delegating behavior through abstraction provided by interface resulting in less lines of code. I always believed less lines of code is not only a representation of syntactic sugar but rather an expressive simplicity. Fewer lines of code results in code which is less prone to error.

The remaining question though, is this too much magic? I would describe them as party tricks. They are fun to know and play around with but does it really solve the problem in a more sustainable manner? Will your co-workers understand the code? Does it reduce the underlying complexity? Consistency should be the answer. Make it a known paradigm and introduce it to the whole code base. Otherwise, if it is a one-off just to show off your proficiency, drop it.