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

This is the most complete version of the talk, containing as many different refactorings as I could squeeze in, and updated performance analysis.

Other versions include:

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

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

Streams

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.

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