Default Methods


Idioms and Techniques

Design Rationale

Advanced Questions

Why are lambda expressions being added to Java?

Lambda expressions (and closures) are a popular feature of many modern programming languages. Amongst the different reasons for this, the most pressing one for the Java platform is that they make it easier to distribute processing of collections over multiple threads. Currently, lists and sets are typically processed by client code obtaining an iterator from the collection, then using that to iterate over its elements and process each in turn. If the processing of different elements is to proceed in parallel, it is the responsibility of the client code, not the collection, to organise this.

In Java 8, the intention is instead to provide collections with methods that will take functions and use them, each in different ways, to process their elements. (We will use as an example the very simple method forEach, which takes a function and just applies it to every element.) The advantage that this change brings is that collections can now organise their own iteration internally, transferring responsibility for parallelisation from client code into library code.

However, for client code to take advantage of this, there needs to be a simple way of providing a function to the collection methods. Currently the standard way of doing this is by means of an anonymous class implementation of the appropriate interface. But the syntax for defining anonymous inner classes is too clumsy to be practicable for this purpose.

For example, the forEach method on collections will take an instance of the Consumer interface and call its accept method for every element:

    interface Consumer<T> { void accept(T t); } 

Suppose that we want to use forEach to transpose the x and y co-ordinates of every element in a list of java.awt.Point. Using an anonymous inner class implementation of Consumer we would pass in the transposition function like this:

    pointList.forEach(new Consumer<Point>() { 
        public void accept(Point p) { 
            p.move(p.y, p.x);

Using a lambda, however, the same effect can be achieved much more concisely:

    pointList.forEach(p -> p.move(p.y, p.x));