Java Lambda Expressions

clip_image002 SEPTEMBER/OCTOBER 2012

Java Language Architect Brian Goetz
explains the importance of lambda expressions, which are coming in Java SE 8.


Adding lambda expressions—known also as closures—to the Java language provides developers, especially API designers, with a sharper tool for abstracting over behavior. While Java developers already have some tools with which to do so, the compactness of lambda expressions will definitely change the game in terms of what code is natural to write.

Take collections. The way to enumerate the elements of a collection is to ask for an iterator, and pull elements from the iterator, a task that is automated by the for-each loop:

for (Person p : people) {
// do stuff with p

This is an idiom called external iteration. It is perfectly straightforward, but it has a lot of accidental characteristics that have nothing to do with the task of operating on each element of a collection—it is inherently sequential, elements must be processed in the order in which they appear in the collection, and the client is responsible for the mechanics of iteration. On the other hand, internal iteration lets the client pass some behavior to the collection to be applied to each element:

people.forEach(p -> { /* do stuff with p*/ });

While this may seem no different, some very big things have changed— the library is now in control of the mechanics of the computation. While the client still specifies the what, it no longer specifies the how—and this is a good thing. Maybe the library will use parallelism, or exploit what it knows about memory locality to process elements in an order that is more efficient, or any number of other techniques for getting to the right answer faster.

For example, take the problem “find the groups that have at least one employee over 65, and print them in increasing order of size.” 
Today, we might write this as follows:

List<Employee> people = …
Set<Group> groups = new HashSet<>();
for (Person p : people) {
    if (p.getAge() >= 65) groups.add(p.getGroup());
List< Group> sorted = new ArrayList<>(groups);
Collections.sort(sorted, new Comparator<Group>() {
     public int compare(Group a, Group b) {

for (Group g : sorted) System.out.println(g.getName());

This is kind of ugly. We have several garbage variables here—groups and sorted—that exist only to hold intermediate results. The code is very adhoc; small changes to the problem statement will have big ripple effects on the code. There’s a lot of copying of data to get it into and out of the intermediate collections. And you have to read the data carefully to see what is going on.

Lambda-enabled collection libraries offer a much cleaner way to express this computation:

people.filter(p -> p.getAge() > 65)
    .map(p -> p.getGroup())
    .sorted(comparing(g -> g.getSize())
    .forEach(g -> System.out.println(g.getName());

There are no garbage variables, and you can read the computation from top to bottom and see exactly what is going on. It is the ability of the library to let the user parameterize the computation with little bits of functionality that drives this sort of library design, which makes things easier (and often more efficient) for the user. Moreover, small changes to the problem statement are more likely to result in small changes to the code.

By migrating from an external iteration model to an internal iteration model, parallelism is one more thing that we can move into the library.
The above query can be parallelized with a small change:

   .filter(p -> p.getAge() > 65)
   .map(p -> p.getGroup())
   .sorted(comparing(g -> g.getSize())
   .forEach(g -> System.out.println(g.getName());

All that has changed is the insertion of the parallel() and sequential() calls;
the filter/map/sort can now happen in parallel, and at the end when we want to process the elements in order, we switch back to serial mode.

Ovaj unos je objavljen u Nekategorizirano. Bookmarkirajte stalnu vezu.


Popunite niže tražene podatke ili kliknite na neku od ikona za prijavu: Logo

Ovaj komentar pišete koristeći vaš račun. Odjava / Izmijeni )

Twitter picture

Ovaj komentar pišete koristeći vaš Twitter račun. Odjava / Izmijeni )

Facebook slika

Ovaj komentar pišete koristeći vaš Facebook račun. Odjava / Izmijeni )

Google+ photo

Ovaj komentar pišete koristeći vaš Google+ račun. Odjava / Izmijeni )

Spajanje na %s