Tuesday, October 7, 2014

Java 8 Overview: Lambdas

Probably one of the most requested features and biggest time saver in Java 8 are lambdas. Essentially, a lambda is a short hand way to create an anonymous inner class. Let's look at how we used to have to do an anonymous comparator for comparing the lower case result of strings in a list:
    Collections.sort(comparison, new Comparator<String>() {
        @Override
        public int compare(String o1, String o2) {
            return o1.toLowerCase().compareTo(o2.toLowerCase());
        }
    });
Even with this simple example you can see quite a bit of extra code you have to write just to put in the logic of comparing two strings in lower case. Now, in Java 8 with lambdas you can compress the previous statement to the following:
Collections.sort(comparison, (o1, o2) -> o1.toLowerCase().compareTo(o2.toLowerCase()));
Much simpler right?

Lambda requirements

There is basically a single requirement for an interface to be used as a lambda expression. The interface needs to be annotated with the @FunctionalInterface annotation. This annotations requires a single non default, non static method in the interface. This way, with only a single method available it's obvious what method should be called and what the parameters and return type are for the method call. When it comes to creating lambdas there are essentially two types, what I call simple lambdas and standard lambdas.

Simple Lambdas

Simple lambdas consist of a single expression where the result of that expression is returned. They don't require braces and you can also omit the return keyword as well. The following is an example of what one would look like:
Collections.sort(comparison, (o1, o2) -> o1.toLowerCase().compareTo(o2.toLowerCase()));
In these cases even more of the code that is unnecessary is removed to make the result even cleaner.

Standard Lambdas

You would use a standard lambda when your implementation requires multiple statements. In these cases you would enclose the statements within braces and you need to include the return statement for all return points. If you were to compare a list of users based on their last name then first name then the expression would look something like the following:
        Collections.sort(comparison, (User o1, User o2) -> {
            int compare = o1.getLastName().compareTo(o2.getLastName());
            return compare != 0 ? compare : o1.getFirstName().compareTo(o2.getLastName());
        });
As you can see above, when items become more complex you have to specify the object types (User o1, User o2 instead of just o1, o2 like for the simple setup), you have to use braces and a return statement.

Extra information

To cut the code necessary for working with lambdas even further Java 8 includes a set of the most common types of operations you'd perform in the java.util.function package. In there you'll find operations such as Functions for processing one property and returning a result, predicates that take in an argument and return a boolean result, and a whole host of other standard operations. They're used heavily by streams (more on that in a future blog post) and can easily be integrated in your code base.

Conclusion

While lambdas don't introduce a new programming archetype in the language they do greatly simplify the code you need to write (and thus read as well). Like annotations before them they help to make the code more concise and easier for others to work with and understand. Finally, albeit to a lesser extent, it shows that Java can still move with the times and incorporate current programming paradigms to help coders in other languages to relate to the code.

No comments:

Post a Comment