Twitter GitHub Facebook Instagram dirv.me

Daniel Irvine on building software

Java 8 lambdas and the Function interface

17 September 2014

Java 8 has support for functional programming constructs which will save you time and effort. Here’s one example of that. The Function<T, R> interface can be used to pass lambdas between method calls. Here’s what it looks like (check the SDK docs for the full rundown):

public interface Function<T,R>
{
  R apply(T t);
}

What this is really saying is: “given an object of type T, convert it into an object of type R.” Crucially, all lambda expressions in Java 8 take take one parameter will automatically implement this interface:

str -> Integer.parseInt(str)  // implements Function<String, int>

That means you can pass objects that satisfy this interface without having to define a class (anonymous or otherwise). It turns out that the Function<T, R> interface is common enough for this to be very useful.

And actually, the example lambda can be simplified even further as we’ll see in the following example.

Imagine we have a console application that asks questions of the user, expecting answers of various types and validating the answer based on a set of allowed answers.

Which color? Red
How many game rounds? 5

We can implement this functionality concisely using lambda expressions. Here’s the ask method, which takes a lambda to do its type conversion:

private <T> T ask(String question, List<T> validAnswers, Function<String, T> convert)
{
  T answer = null;
  while(!validAnswers.contains(answer))
  {
    try {
      out.println(question);
      answer = convert.apply(in.readLine().trim());
    } catch(Exception ex) {
    }
  }
  return answer;
}

It can then be used like this:

Color[] validColors = new Color[] { Color.blue, Color.red };
Color playerColor = ask(Which color?, validSizes, s -> Color.getColor(s));

int[] validRounds = new int[] { 3, 5, 7 };
int rounds = ask(How many game rounds?, validRounds, s -> Integer.parseInt(s));

Using member references, another Java 8 feature, we can simplify the method calls even further:

Color[] validColors = new Color[] { Color.blue, Color.red };
Color playerColor = ask(Which color?, validSizes, Color::getColor);

int[] validRounds = new int[] { 3, 5, 7 };
int rounds = ask(How many game rounds?, validRounds, Integer::parseInt);

The functionality shown here could be implemented fairly simply using anonymous classes. The Function<T, R> interface gives us another way to do this in a slightly simpler fashion.

About the author

Daniel Irvine is a software craftsman at 8th Light, based in London. These days he prefers to code in Clojure and Ruby, despite having been a C++ and C# developer for the majority of his career.

For a longer bio please see danielirvine.com. To contact Daniel, send a tweet to @d_ir or use the comments section below.

Twitter GitHub Facebook Instagram dirv.me