Report: Will Java 8’s Lambda Change The Face of The World?
Java 8 will be delivered in less than one year. One of the most impacting projects that will appear with this version certainly is the Lambda Project, referenced as JSR335 and supervised by Brian Goetz. This project aims to provide you an easier way to integrate functional programming and parallel computing. The goal is to improve the productivity of developers by enhancing the expressivity of the language and to optimize the performance of Java application by offering an easier way to exploit multi-core architectures. But what will be the impact on the Java community of the results of the Project Lambda?
I am a member of Xebia France. Like Xebia Netherlands, we dedicate a day every month to the exchange of knowledge (also called XKE – Xebia Knowledge Exchange). I took the opportunity of the XKE of October to propose a session and ask my colleagues: will the modifications brought by the Lambda Project be eventually adopted by the Java world —including the Java community and the projects in companies— or will these modifications be rejected? The session had a somewhat provocative title: “Will Java 8’s Lambda Change The Face of The World?”
During this session, 16 Xebians were present, including one of our two CTOs and myself. Generally, the audience was composed of java programmers with an experience in this language between 2 and 10 years, and even more. Many of us are knowledgeable in other programming paradigms (eg. functional programming) as well.
The 3-hours XKE session was structured around a presentation. It was followed by sequences of live coding and debates. The session ended with a retrospective.
The session presentation about Project Lambda was divided into three main sections. It started with a section describing the context of the Project Lambda (optimization for multi-core architectures and improvement of the productivity of developers) and its motivation. Then, I showed to the audience a section about the lambda expressions in Java 8, the virtual extension methods, and also the method references, the extension of the API collection in JDK, and how easy it will become to build concurrent processes. I ended by a section describing the way the project is managed and its relationship with the community (team members of the Project Lambda, Web sites, mailing lists, enthusiast people (especially in France) who are taking part in the promotion of the Project Lambda). I have also brought my own appreciation on the relation between Project Lambda and the community.
Live coding and debates
The live coding part was composed of a set of exercises based on unit tests. The first three exercises showed the differences between imperative Java, Guava, and the use of lambda expressions in Java 8 in a view to process collections. Then, we experienced that the lambda expressions help to express the notions of call-by-value and call-by-name in method calls.
We used an exercise proposed by Martin Odersky (creator of Scala) at ScalaDays’2011. Knowing that each key on a phone is associated to mnemonics (eg. for the key ‘2’, you have the mnemonics ‘A’, ‘B’, and ‘C’), the kata aimed to reproduce the behavior of the auto-completion when writing a SMS.
Next, we did a set of exercises around the virtual extension methods, their use and the way they solve the diamond problem. I have also presented the optimisation made for the lambda expressions that are independent from the state of the other parts of the application.
We ended with a micro-benchmark on the processing of huge collections by using on the one hand the sequential operations and on the other hand parallel operations. We noticed a performance gain on a quad-core architecture for the parallel version and how easy it was to realize this gain.
This part of the session is certainly the one that provoked the most reactions from the audience. There were many questions, reflections, challenges too, and… trolls. The live coding and the debates were certainly one of the parts of the session where the audience got a better vision on Java 8. It helped them a lot to share their viewpoints.
You will find the code produced during the session on github.
The retrospective was based upon a Speed Car. A speed car tells the story of a pilot who has to find a car as powerful as possible. His goal is to cross a bridge quickly. The bridge must not collapse. If the pilot reaches the other side of the bridge, he succeeds in its project.
Of course, the speed car is a metaphor. On the one side of the picture, the car-parachute part of the picture represents the Lambda Project of Java 8 at present, with its new syntax, the new collection API, and the way the project is managed. More exactly, the car reflects what is the driving force behind the project and the parachute is linked to what tends to slow it down. On the other side of the picture, the bridge-abyss part represents the future of the Lambda Project. In other words, the bridge is what keeps the project going (the community, the adoption in projects, etc.). The abyss must be seen as a partial or even complete rejection of the new features of Java 8.
Photo of the results of the retrospective (in French)
Results of the retrospective and of the rest of the session
To conclude the session, here are the points that were highlighted by the participants.
Provide a guide containing best practices
Java 8 will be delivered with new features. These features will help the developer to gain productivity. But, it is easy to imagine that bad practices will spread, because there certainly will be many developers that will be unable to use the improvements of Java 8 correctly. Ideally, developers must be guided. This can be done by providing best practices through a guide.
The new syntax is nice, but not for everyone
The simplification of the syntax in general has been appreciated by the participants. But, the majority would like to see even more simplifications, especially for the chained expressions. For example, we are obliged to call the method map in a view to do a transformation prior to call the reduce. This has been perceived as a “clumsy expression”. The same holds for the intermediary call to stream: why operation on stream are not directly in the collections (List, Set, Map, etc.)?
The current syntax looks like this, due to the signature of the operations “map” and “reduce”:
.map(product -> product.getUnitPrice() * product.getQuantity())
.reduce(0.0, (subTotal, price) -> subTotal + price)
But, some people didn’t understand why we have to separate the operation “product.getUnitPrice() * product.getQuantity()” from “subTotal + price”. They have said that the separation of “map” and “reduce” is more difficult to read. From their point of view, it would be better to have these operations put together, like this:
(subTotal, price) -> subTotal + product.getUnitPrice() * product.getQuantity())
There were remarks about the lack of implicit parameters like “it” in Groovy or “_” in Scala. Some people said that the presence of such parameter would be appreciable.
Lastly, some people think that the code is not easy to read, especially in the case of the chaining of map and reduce.
The virtual extension methods
The virtual extension methods represent a way to extend the existing API in the JDK without forcing the existing implementations to provide new code for these extensions. For example, the collection API of Java will contain new methods to do bulk operations and to parallelize them. As an example, with the virtual extension methods, Hibernate will not be obliged to reimplement all the new extensions of the collection API for its PersistentCollection.
But, will the virtual extension methods not introduce new confusion? For example, it is possible to provide a default implementation of a method m of an interface and not force its sub-classes to reimplement m. In an inheritance tree, it is possible to alternate between default implementation and no implementation. This can lead to confusion in the resulting behavior of m.
One of remaining points of concern regarding Project Lambda is the way Javadoc will handle the virtual extension methods. Since they introduce behavior in the interface, the corresponding the Javadoc becomes critical.
One of the participants has argued that there will inevitably be lots of trolls from developers, especially those specialized in functional programming. To this, another participant has answered that those trolls will in a sense spread some publicity that may stir up the curiosity of the developers.
- Some members think that the lambda in Java 8 comes too late, as there are at present many other competitive solutions: Scala, Groovy, Clojure, and even Guava for the Collection API.
- The lambda in Java 8 are in a sense anonymous inner classes and have no dedicated type. In a sense, this highlights the Java debt.
- It seems difficult to debug the chains of method call like
filter(x -> ...).map(y -> ...).reduce((u, v) -> ...)
- It will be interesting to get the results of benchmarks between sequential streams and parallel streams.
- Java 8 introduces a new syntax. Will this increase the time of compilation?
It was an exciting session. Most remarks and reflections were very interesting, even if there were some trolling concerns. They mostly deserve to be reported. The format I have chosen for this session has helped to get rich reactions from the audience, even if the time available was relatively short. I encourage you to organize such a session.