JVM Languages

Lambda Expressions in Java 8

By Cay S. Horstmann, March 25, 2014

The single most important change in Java 8 enables faster, clearer coding and opens the door to functional programming. Here's how it works.

Java was designed in the 1990s as an object-oriented programming language, when object-oriented programming was the principal paradigm for software development. Long before there was object-oriented programming, there were functional programming languages such as Lisp and Scheme, but their benefits were not much appreciated outside academic circles. Recently, functional programming has risen in importance because it is well suited for concurrent and event-driven (or "reactive") programming. That doesn't mean that object orientation is bad. Instead, the winning strategy is to blend object-oriented and functional programming. This makes sense even if you are not interested in concurrency. For example, collection libraries can be given powerful APIs if the language has a convenient syntax for functional expressions.

The principal enhancement in Java 8 is the addition of functional programming constructs to its object-oriented roots. In this article, I demonstrate the basic syntax and examine how to use it several important contexts. The key points are:

A lambda expression is a block of code with parameters.

Use a lambda expression whenever you want a block of code executed at a later point in time.

Lambda expressions can be converted to functional interfaces.

Lambda expressions can access effectively final variables from the enclosing scope.

Method and constructor references refer to methods or constructors without invoking them.

You can now add default and static methods to interfaces that provide concrete implementations.

You must resolve any conflicts between default methods from multiple interfaces.

Why Lambdas?

A lambda expression is a block of code that you can pass around so it can be executed later, just once or multiple times. Before getting into the syntax (or even the curious name), let's step back and see where you have used similar code blocks in Java all along.

When you want to do work in a separate thread, you put the work into the run method of a Runnable, like this:

The sort method keeps calling the compare method, rearranging the elements if they are out of order, until the array is sorted. You give the sort method a snippet of code needed to compare elements, and that code is integrated into the rest of the sorting logic, which you'd probably not care to reimplement. Note that the call Integer.compare(x, y) returns zero if x and y are equal, a negative number if x < y, and a positive number if x > y. This static method was added to Java 7. You shouldn't compute x - y to compare x and y because that computation can overflow for large operands of opposite sign.

As another example for deferred execution, consider a button callback. You put the callback action into a method of a class implementing the listener interface, construct an instance, and register the instance with the button. That happens so often that many programmers use the "anonymous instance of anonymous class" syntax:

What matters is the code inside the handle method. That code is executed whenever the button is clicked.

Since Java 8 positions JavaFX as the successor to the Swing GUI toolkit, I use JavaFX in these examples. (See Eric Bruno's posts for more information on JavaFX.  Ed.) The details don't matter. In every user interface toolkit, be it Swing, JavaFX, or Android, you give a button some code that you want to run when the button is clicked.

In all three examples, you saw the same approach. A block of code was passed to someone  a thread pool, a sort method, or a button. The code was called at some later time.

Up to now, giving someone a block of code hasn't been easy in Java. You couldn't just pass code blocks around. Java is an object-oriented language, so you had to construct an object belonging to a class that has a method with the desired code.

In other languages, it is possible to work with blocks of code directly. The Java designers have resisted adding this feature for a long time. After all, a great strength of Java is its simplicity and consistency. A language can become an unmaintainable mess if it includes every feature that yields marginally more-concise code. However, in those other languages, it isn't just easier to spawn a thread or to register a button-click handler; large swaths of their APIs are simpler, more consistent, and more powerful. In Java, one could have written similar APIs that take objects of classes implementing a particular function, but such APIs would be unpleasant to use.

For some time now, the question was not whether to augment Java for functional programming, but how to do it. It took several years of experimentation before a design emerged that is a good fit for Java. In the next section, you will see how you can work with blocks of code in Java 8.

The Syntax of Lambda Expressions

Consider the previous sorting example again. We pass code that checks whether one string is shorter than another. We compute

Integer.compare(first.length(), second.length())

What are first and second? They are both strings! Java is a strongly typed language, and we must specify that as well:

You have just seen your first lambda expression! Such an expression is simply a block of code, together with the specification of any variables that must be passed to the code.

Why the name? Many years ago, before there were any computers, the logician Alonzo Church wanted to formalize what it means for a mathematical function to be effectively computable. (Curiously, there are functions that are known to exist, but nobody knows how to compute their values.) He used the Greek letter lambda (λ) to mark parameters. Had he known about the Java API, he would have written:

λfirst.λsecond.Integer.compare(first.length(), second.length())

Why the letter λ? Did Church run out of other letters of the alphabet? Actually, the venerable Principia Mathematica used the ˆ accent to denote free variables, which inspired Church to use an uppercase lambda (Λ) for parameters. But in the end, he switched to the lowercase version. Ever since, an expression with parameter variables has been called a "lambda expression."

Dr. Dobb's encourages readers to engage in spirited, healthy debate, including taking us to task.
However, Dr. Dobb's moderates all comments posted to our site, and reserves the right to modify or remove any content that it determines to be derogatory, offensive, inflammatory, vulgar, irrelevant/off-topic, racist or obvious marketing or spam. Dr. Dobb's further reserves the right to disable the profile of any commenter participating in said activities.

Video

This month's Dr. Dobb's Journal

This month,
Dr. Dobb's Journal is devoted to mobile programming. We introduce you to Apple's new Swift programming language, discuss the perils of being the third-most-popular mobile platform, revisit SQLite on Android
, and much more!