• Skip to primary navigation
  • Skip to main content
  • Skip to footer

Codemotion Magazine

We code the future. Together

  • Discover
    • Events
    • Community
    • Partners
    • Become a partner
    • Hackathons
  • Magazine
    • Backend
    • Frontend
    • AI/ML
    • DevOps
    • Dev Life
    • Soft Skills
    • Infographics
  • Talent
    • Discover Talent
    • Jobs
    • Manifesto
  • Companies
  • For Business
    • EN
    • IT
    • ES
  • Sign in
ads

Vito GentileMarch 2, 2020

Lazy Java

Backend
facebooktwitterlinkedinreddit
Table Of Contents
  1. Introduction
  2. Functional Programming
  3. Lazy Evaluation and Java 8 Streams

Introduction

Laziness is one of the three great virtues of any programmer according to Larry Wall, author of the book Programming Perl. Consequently, it is no surprise that Mario Fusco, senior software engineer at Red Hat, highlighted the power of lazy evaluation in Java, which represents an interesting approach for code optimisation. The two ideas are in fact related: lazy programmers tend to delay things until they are really needed; and lazy evaluation consists of delaying the evaluation of an expression until its value is needed.

Mario Fusco was invited to deliver a speech at Codemotion Milan 2018, and he focused on how to apply lazy evaluation in Java. In fact, Java methods are strict, since they evaluate their arguments as soon as they are passed to them. However, even if Java is mainly a strict language, there are some exceptions. For instance, boolean operators && and || are lazy, since the second operand is not evaluated, the first is deemed sufficient for computing the resulting boolean value. The same considerations apply to if-else, ternary operator ? :, for/while loops, and the Java 8 streams.

Recommended article
June 10, 2025

VanillaCreamJS: Superpowers for Native JavaScript

Riccardo Degni

Riccardo Degni

Backend

Functional Programming

In general, we can exploit the support to functional programming in order to turn Java into a lazy language. To explain how, Mario Fusco started from a simple example, which re-implements the ternary operator:

<T> T ternary(boolean pred, T first, T second) {
    if (pred) {
        return first;
    } else {
        return second;
    }
}

String val1() {
    return "first";
}
String val2() {
    return "second";
}

String result1 = bool ? val1() : val2();
String result2 = ternary(bool, val1(), val2());

The above code snippet is strict: indeed, in order to execute the ternary method, the arguments val1() and val2() need to be both evaluated. Consequently, we cannot obtain the desired behaviour with this strategy. However, Suppliers allows to turn the above code into lazy, as show by the following code snippet:

<T> T ternary(boolean pred, Supplier<T> first, Supplier<T> second) {
    if (pred) {
        return first.get();
    } else {
        return second.get();
    }
}

String val1() {
    return "first";
}
String val2() {
    return "second";
}

String result1 = bool ? val1() : val2();
String result2 = ternary(bool, () -> val1(), () -> val2());

As you can see, optimising the code by exploiting lazy evaluation is quite easy. And accordingly to Mario Fusco, “laziness is probably the only form of performance optimisation which is (almost) never premature”. Indeed, “there is nothing so useless as doing efficiently something that should not be done at all”.

Lazy Evaluation and Java 8 Streams

As mentioned before, Java 8 Streams represent one of the construct that are lazy by definition. Consider the following example:

IntStream.iterate( 1, i -> i+1 )
         .map( i -> i * 2 )
         .filter( i -> i > 5 )
         .findFirst();

Thanks to the lazy nature of streams, the iterate method allows to create streams that are potentially infinite. Indeed, this method does not create any data structure, but it demands the data generation to the terminal operation (in this case the findFirst method). Same considerations apply to the map and filter methods: intermediate operations are lazy, since they do not perform any action before the terminal operation. These considerations point to a key concept: streams are not data structures, but rather lazy specifications of how to manipulate data.

Putting these ideas into practice should seem conceptually simpler now. However, this is not exactly the case. In fact, Java still has many limitations that, for instance, have been implemented differently in Scala or other languages more oriented towards functional programming. Mario Fusco shared his presentation on SlideShare, where you can find many other interesting examples to understand the practical difficulties in using lazy evaluation in Java.

Related Posts

Start building REST APIs with Django REST Framework

raffaelegrieco.it
May 13, 2025

Top 10 online platforms to practice Python every dev should know

Lucilla Tomassi
May 13, 2025

.NET Refactoring Series: Episode 1 — How to Approach Service Refactoring

giovanni-ferrari
April 2, 2025

Queueing Without a Queue: The PostgreSQL Hack

Puppo92
March 13, 2025
Share on:facebooktwitterlinkedinreddit

Tagged as:Codemotion Milan Functional Programming Java

Vito Gentile
I’m a data scientist, tech writer, software developer with experience in mobile, web (full-stack) and Python programming, and former researcher with interests in human-computer interaction. I thus have a multi-faceted experience in the area of software development, and that’s why I love my job(s)!
Codemotion Community Platform: Full User Guide
Previous Post
Codemotion Rome 2020: an overview of the companies involved
Next Post

Footer

Discover

  • Events
  • Community
  • Partners
  • Become a partner
  • Hackathons

Magazine

  • Tech articles

Talent

  • Discover talent
  • Jobs

Companies

  • Discover companies

For Business

  • Codemotion for companies

About

  • About us
  • Become a contributor
  • Work with us
  • Contact us

Follow Us

© Copyright Codemotion srl Via Marsala, 29/H, 00185 Roma P.IVA 12392791005 | Privacy policy | Terms and conditions