Java Development News:

Lambda, Java 8, interface evolution and laws of unintended consequences

By Cameron McKenzie

26 Sep 2013 | TheServerSide.com

At JavaOne 2013, the upcoming release of Java 8 is on the tip of everyone's tongues. And when people talk about Java 8, what they're often talking about is Project Lambda -- the changes to the concept of the Java interface that was required to make Lambda work -- and the potential for unintended consequences causing future hardship for the language.

JavaOne ad button Java 5, which first became generally available in 2004, was the last major Java development kit (JDK) release to significantly change the syntax of the language. Forward-thinking software engineers enthusiastically explained their rationale for including things like generics, annotations and varargs, while developers scratched their heads over the weird assortment of inequality signs, asperands and dots at the end of an argument list. The soon-to-be-released Java 8 will make bigger changes to the language than any other release in its history. Once again, engineers are excited and everyday users of the language are grappling with fear of the unknown.

Addressing the deficiencies of Java

A common complaint targeted at the Java programming language is its verbosity. In fact, the desire to simplify the syntax was one of the primary reasons why James Strachan, creator of the Groovy programming language, began his quixotic quest to create a new Java virtual machine (JVM) language. There is no doubt that Java contains a great deal of repetitive, boilerplate code. It's often asserted that Java's verbosity can obfuscate the purpose of a given page of code, which can make maintenance and quality assurance difficult. "When you have code that is hard to read, that's where bugs come from" said Brian Geotz, Java language architect at Redwood Shores, Calif.-based Oracle, at the JavaOne 2013 technical keynote.

Taking a look at a simple example from Geotz' keynote, it's clear that the new Java 8 Lambda syntax is significantly more compact and readable, even if the syntax may not be recognizable to a traditional Java developer.

Traditional Java Code

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) { 
return Integer.compare(a.getSize(), b.getSize()) 

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

The previous code rewritten for Java 8

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

The latter approach using Lambda is not only more syntactically concise, but it's also significantly more efficient, using far fewer clock cycles than the traditional approach. "It turns out to be quite efficient" said Geotz when talking about the manner in which Lambda expressions operate on data collections. "It doesn't do any of the work until it gets to the last step, so it can fuse the filtering, mapping and aggregation operations into one pass on the data." When operating on large data sets, this can significantly reduce the processing time required.

Simplified parallel processing

And if a simplified syntax with more efficient data processing doesn't sell you on Project Lambda, perhaps the fact that it greatly simplifies the task of parallel processing by abstracting away the convoluted fork-join application programming interface (API) from Java 7, will.

The beauty and functionality of a Java interface is tied directly to its simplicity.

"We have inverted the flow of control in the operation," Geotz said, comparing Lambda code with traditional code that uses an iterator. When using an iterator, the user controls how collections are processed and when parallel processing should occur. With Lambda, the user simply describes how a collection should be manipulated and the framework abstracts away the low-level processing details. "With Lambda, the client says to the library, 'here is the function.' And that's what enables the library to do the parallelism without the user having to write all of the fork-join junk. It uses fork-join under the hood, breaks it down and does a parallel decomposition."

Of course, maintaining backwards compatibility between Lambda and the old collections API comes at a price. Two new methods, stream and parallelStream, need to be added to the collection interface for Lambda expressions to work properly. Unfortunately, doing so would mean redefining the collection interface, eliminating any backwards compatibility with previous versions. "We could make a new collections framework, but then people would have to migrate to it and it would take five years for that to happen. If we add Lambda to the language, but we don't make collections work with it, then our old collections look even older," Geotz said.

Redefining the Interface construct

So in order to introduce Lambda expressions while permitting backwards compatibility with older code, the concept of a Java interface is being redefined. Before Java 8, interfaces could only contain abstract methods and constants. However, starting with Java 8, interfaces will be permitted to contain defensive methods. "We finally bit the bullet and addressed the problem of interface evolution,"Geotz said. "We added a concept called default methods. This allows you to add a method to an interface in a compatible way, as long as you provide a default implementation."

This is, without a doubt, the big language change that makes Java aficionados the most uncomfortable. While everyone understands the motivation behind Lambda, such a drastic change to a fundamental language feature makes it seem as though these new Java 8 features are being shoehorned in, forced to fit in a way that isn't natural or elegant. The beauty and functionality of a Java interface is tied directly to its simplicity. The introduction of default methods complicates the concept significantly, and it will no doubt become a feature that will be misused and abused, leading to code that is less readable and maintainable.

There is no debating the fact that the Java language requires an update in order to keep up with all of the innovative advances various languages like Scala, Closure and Groovy have brought to the JVM. Let's hope the changes being made to core language constructs to accommodate Lambda don't have unintended consequences that make the community look back and regret the changes Java 8 has made.