Applying Java 8 Idioms to Existing Code

  • Understand how to improve performance with your Java code using Java 8 language features.
  • Learn hands on techniques to discover and implement common Java 8 refactorings.
  • Understand when you should and should not apply key refactorings in Java 8.

Abstract

While we’re drawing ever closer to Java 9, and even hearing about features in Java 10, many of us are still working with an older version. Even if your project has technically adopted Java 8, and even if you’re using it when coding new features, it’s likely that the majority of your code base is still not making the most of what’s available in Java 8 - features like Lambda Expressions, the Streams API, and new Date/Time. And this is a shame, since Java 8 provides not only nicer syntax for developers, but (usually) better application performance.

In this presentation, Trisha will:

  • Highlight the performance benefits of using Java 8 - after all, you’ll probably have to persuade “The Management” that tampering with existing code is worthwhile
  • Demonstrate how to identify areas of code that can be updated to use Java 8 features, and how to pick which changes will give you the most benefit
  • Demonstrate how to automatically refactor your code to make use of features like lambdas and streams
  • Cover some of the pros and cons of using the new features - including suggestions of when refactoring may NOT be the best idea.

The talk

Most recent version, containing performance analysis, is on the InfoQ website, and InfoQ also has a nice summary of the points covered in the talk.

The first appearance was at DevoxxUK.

You can purchase a more in-depth tutorial on informIT, and is also available via Safari Books Online.

The IntelliJ-specific features of some of the refactoring shown are covered in my Migrating to Java 8 tutorial.

Background

Article: Why Java 8
Article: Five Java 8 Features You Won’t Be Able to Live Without
Video and Research: Building a Java 8 Application

Code

The project we’re refactoring is Morphia. You can see the “after” of the chosen refactorings on the r2j8 branch.

The performance tests that were written and run specifically for this talk are in the j8-morphia-perf-tests repository

Performance

Lambda Expressions

Video: Lambda Performance and talk slides
Article: Java 8 Lambdas - A Peek Under the Hood
Video: Lambdas in Java: A Peek under the Hood - Brian Goetz

Streams

Video: Let’s Get to the Rapids: Java 8 Stream Performance
Article: Java performance tutorial: How fast are the Java 8 streams? - Angelika Langer Notable Quotes:

Again, the for-loop is faster that the sequential stream operation, but the difference on an ArrayList is not nearly as significant as it was on an array.

 

You will find that there is no measurable difference any more between for-loop and sequential stream if the functionality is heavily cpu bound.

 

The point to take home is that sequential streams are no faster than loops. If you use sequential streams then you don’t do it for performance reasons; you do it because you like the functional programming style.

 

The reality check via our benchmark yields a ratio (sequential / parallel) of only 1.6 instead of 2.0, which illustrates the amount of overhead that is involved in going parallel and how (well or poorly) it is overcompensated (on this particular platform).

 

With this in mind it is fair to say that the performance model of streams is not a trivial one

 

…you need to benchmark a lot in order to find out for a given context whether going parallel is worth doing or not.

 

The realisation is: Yes, parallel stream operations are easy to use and often they run faster than sequential operations, but don’t expect miracles. Also, don’t guess; instead, benchmark a lot.

Article: Benchmark: How Misusing Streams Can Make Your Code 5 Times Slower - interesting comparison of different iteration styles. Also shows that things like boxing might add more cost than streams (but that you don’t realise you’re boxing)

Article: Stream Performance - some interesting benchmarks based on Angelika Langer’s article
Article: Follow up on Stream Performance

Date and Time

Article: JSR 310 – Java 8 Date/Time library performance (as well as Joda Time 2.3 and j.u.Calendar)

Benchmarking

I used a bunch of techniques to produce the benchmarks on the talk. I’d like to summarise them more thoroughly when I get a chance, but for now here’s my background reading:

Article: Avoiding Benchmarking Pitfalls on the JVM

Tool: JMH
Tool: IntelliJ JMH Plugin
Article: Introduction to JMH

“Best Practice”

I dislike the term “Best Practice” as it implies a “one size fits all” approach, and I believe that our job is to make difficult decisions based on various pros and cons and differing situations. However, here I will collect resources that may help us make some of those decisions

Article: Refactoring with Loops and Collection Pipelines - Martin Fowler
Slides: Workflows of Refactoring - Martin Fowler
Book: Refactoring: Improving the Design of Existing Code - Martin Fowler

Article: Using Optional in Java SE 8 - Stephen Colebourne
Article: Java 8 Best Practices Cheat Sheet - ZeroTurnaround