Java 8 Lambda's are nice but nothing exciting

Published Mar 06, 2018Last updated Apr 09, 2018
Java 8 Lambda's are nice but nothing exciting

Lambda - sounds pretty intimidating but they're actually pretty simple, and they do not do anything you can't already do. I like them because when used properly, they can make code that little bit clearer; readability is a good thing!

Are you seated? Lambda's are ... just anonymous methods, methods that aren't attached to a class, and that don't require any object instantiation for a to be passed around as arguments to other methods. They are a prettier way to write uber short methods (they don't have to be short, but it is considered a best practice).

There are very few simple rules as to what makes a Lambda (aka functional interface), and just a few best practices.

A Lambda is an interface with only 1 method. For example, the Runnable interface can be used as a Lambda as it only defines the single method run.
For clarity, it is considered best practice to annotate your functional interface with @FunctionalInterface.
It is best practice to avoid mutating any external variables so that the Lambda remain thread-safe.
Best practice to keep your implementation short and sweet.
Use the Java supplied functional interfaces over creating own if possible.
Keep them pure ie the same inputs should always return the same outputs. In this way they can be safely used in Java 8's Streams.

Lambda's using Java 8's 2 in-built functional interfaces

import java.util.function.BiFunction;
import java.util.function.Function;

public class LambdaExample {

    // i'm just using n for name
    static Function<String, String> greet = n -> "Hello " + n;

    // i'm just using s for salutation and n for name
    static BiFunction<String, String, String> bespokeGreet = (s, n) -> s + " " + n;

    public static void main(String[] args) {

        // built-in functional interface that takes a single input arg
        System.out.println(greet.apply("Steve"));

        // built-in functional interface that takes two input args
        System.out.println(bespokeGreet.apply("Yo","Steve"));
    }
}

Alternative to above wihout Lambda's

public class NonLambdaExample {

    static String greet(String n) {
        return "Hello " + n;
    }
    static String bespokeGreet(String s, String n) {
        return s + " " + n;
    }

    public static void main(String[] args) {

        // built-in functional interface that takes a single input arg
        System.out.println(greet("Steve"));

        // built-in functional interface that takes two input args
        System.out.println(bespokeGreet("Yo","Steve"));
    }
}

Not exactly a stark difference in the very simplistic examples above. The bigger difference is seen when passing Lambda's into other methods

Lambda as arg

import java.util.function.Function;

public class LambdaExample {

    // i'm just using n for name
    static Function<String, String> greet = n -> "Hello " + n;


    static void printGreeting(String name, Function<String, String> greetMethod) {
        System.out.println(greetMethod.apply(name));
    }

    public static void main(String[] args) {

        // built-in functional interface that takes a single input arg
        printGreeting("Steve", greet);
    }
}

Vs non-lambda as arg

public class LambdaExample {

    // i'm just using n for name
    String greet(String n) {
        return "Hello " + n;
    }

    static void printGreeting(String name, LambdaExample le) {
        System.out.println(le.greet(name));
    }

    public static void main(String[] args) {

        // built-in functional interface that takes a single input arg
        printGreeting("Steve", new LambdaExample());
    }
}

The main difference? In the non-lambda example we've had to instantiate a new Object for passing as the arg!

Discover and read more posts from Steve Donovan
get started