Do more with less: Lambda expressions in Java 8

Using lambda expressions can make your Java code leaner, more powerful, and easier to read

1 2 Page 2
Page 2 of 2

Lambda syntax in Java
As we saw above, the C# lambda operator is =>. The Java lambda operator is ->. (Don't complain to me about the inconsistency. If the syntaxes were the same, anybody could learn them -- then where would we be?)

Like C# lambda expressions, Java 8 lambda expressions tie an argument list to a body. For example, (int x) -> x * x specifies an integer parameter that's named x and returns the value of x squared. As you can see, Java 8 lambda expressions are typed. Fortunately, when the type can be inferred by the context, it can be omitted.

Consider the following three lambda expressions:

(int x, int y) -> x + y 

() -> 42 

(String s) -> { System.out.println(s); }

Now consider the ActionListener example from above, rewritten with a lambda expression:

JButton testButton = new JButton("Test Button");
testButton.addActionListener(e -> System.out.println("Click Detected by Lambda Listener"));

Much better, don't you think? You'll note that because e is the argument of an ActionListener, it comes under the "target typing" clause and its type is inferred.

Standard functional interfaces
The java.util.function package in Java 8 includes five kinds of standard functional interfaces:

  • Predicate: A property of the object passed as argument
  • Consumer: An action to be performed with the object passed as argument
  • Function: Transform a T to a U
  • Supplier: Provide an instance of a T (such as a factory)
  • UnaryOperator: A unary operator from T -> T
  • BinaryOperator: A binary operator from (T, T) -> T

These are just starting points, as you can always define your own interfaces, but they cover the majority of the cases you'll want to use for lambda expressions.

Collections in Java
Lambda expressions can help streamline the use of Java Collections, even as they existed before Java 8. In addition, Collections have added features that marry well to lambda expressions, including a new forEach() method defined on every Iterator and Iterable interface.

For example (drawing again on that Oracle tutorial), we can define a List of the Person class, which you can assume has an age member:

List<Person> pl = Person.createShortList();

Then we can define a predicate for selection from the list:

Predicate<Person> allDrivers = p -> p.getAge() >= 16;

Finally, we can do something with our selection from the list:

someClass.doSomething(pl, allDrivers);

If you think about it, that's a lot more compact than the pre-Java 8 ways of accomplishing the same task.

If you want to accomplish a slightly more complicated action, it helps to use the forEach() method mentioned earlier:

pl.forEach( p -> p.printWesternName() );

Suppose you want to apply multiple predicates in series? You can use the new filter() method, which takes a predicate as its argument, and you can chain methods together:"allPilots"))

If you think about it, chained filters are inherently more efficient than handwritten loops over collection members. Members that don't meet an early criterion are dropped and never passed to later filters.

You'll notice we used a stream() method at the beginning of our chain -- we needed it to enable chaining. A stream() method takes a Collection as input and returns a interface as the output. A Stream represents a sequence of elements on which various methods can be chained. Streams can be processed serially or in parallel (using the parallelStream method), which opens up additional possibilities of improving performance. Streams are automatically disposed after use. If you need to save the results, you can copy them into another collection.

We could go on to discuss aggregates and the map method, but I think you have the idea by now.

In summary, lambda expressions in Java 8 offer several improvements to the language. They make many kinds of code easier to read and shorter to write, especially code that can be expressed in functional form. They give the language more expressive power. And they make many kinds of operations more efficient at runtime. Based on the experience of the .Net community with LINQ and lambda expressions, adding functional programming to Java will not weaken its object-orientation in any way. It will make the language richer, stronger, and more elegant.

This article, "Do more with less: Lambda expressions in Java 8," was originally published at Follow the latest developments in Java programming and application development at For the latest business technology news, follow on Twitter.


Copyright © 2014 IDG Communications, Inc.

1 2 Page 2
Page 2 of 2