Java 8 Lambda expressions and functional interfaces

Java 8 lambda expressions in functional interfaces
Difficulty

To talk about lambda functions and functional programming we must first talk about functional interfaces.

A functional interface is an interface with one and only one abstract method. They have a special relationship with lambda expressions.
From Java 8 we can find many functional interfaces in java.util.function package.

A functional interface can also have static and default methods. For instance, java.util.function.Predicate has five methods: and(), isEqual(), negate(), or() and only one abstract test() method.

Methods inheritated from Object don’t count so Object.equals() method doesn’t count, like other static and default methods. The only abstract method is callen functional method.

// Foo.java: a functional interface
interface Foo {
  public void foof();
}

...
// An anonymous inner class
  Bar b = new Bar();
  b.doStuff(new Foo() {
    public void foof() {
      System.out.println("foofy");
    }
  });
...

...
// An anonymous inner class
  Bar b = new Bar();
  b.doStuff(() -> System.out.println("foofy"));
...


A famous example of a functional interface is Comparator with its sort() method. In our example DVDInfo is a class of informations about film DVDs and we have to sort by genre a List of DVDInfos.
We can use the classic implementation of Comparator<T>:

class GenreSort implements Comparator<DVDInfo> {
  public int compare(DVDInfo dvd1, DVDInfo dvd2) {
    return dvd1.getGenre().compareTo(dvd2.getGenre());
  }
}


We can set it like an anonymous inner class:

Comparator<DVDInfo> genreSort = new Comparator<DVDInfo>() {
  public int compare(DVDInfo dvd1, DVDInfo dvd2) {
    return dvd1.getGenre().compareTo(dvd2.getGenre());
  }
};
dvdlist.sort(genreSort); // used to sort our list


And from Java 8 we can also use lambda:

dvdlist.sort((dvd1, dvd2) -> dvd.getGenre().compareTo(dvd2.getGenre()));


We can also pass the lambda inside a Comparator<DVDInfo> variable.
Which is your favorite implementation?

Lambda expressions for functional interfaces

Lambda functions are a compact way to use a functional interface. We can transform functional interfaces into lambda expressions.

We can omit something if we have only one argument without type or only a statement.
If we have only one expression we can not use curly braces. Lambda will know that this is a void method and for expressions with return it threats it like returned.

These are all equivalent expressions:

DogQuerier dq = d -> d.getAget() > 9;
DogQuerier dq = (d) -> d.getAget() > 9;
DogQuerier dq = (Dog d) -> d.getAget() > 9;
DogQuerier dq = d -> { return d.getAget() > 9 };

With arg type (Dog in our example above) or with more than one argument w must add parenthesis. If we use return we must add curly braces or also for more than one statement.

A lambda can get variables from its outside enclosing scope but it cannot modify them.
Varibles from outside have to be final or effectively final (whose value isn’t changed after it is initialized).

int numCats = 3;
int numDogs = 1;
DogQuerier dq = d -> {
  int numDogs = 5; // not compiles!
  numCats++; // not compiles!
  System.out.println(numCats); // OK, only accessing
  System.out.println(numDogs); // OK, only accessing
};

If we declare and modify a variable all in a lambda expression it’s ok.

Method References in lambda expressions

There is a shorthand (also called a “sugar syntax”) to write lambda expressions, called method reference.

class Refs {
  public static void main(String[] args) {
    List<String> trees = Arrays.asList("Elm", "Cypress", "Ash");
    trees.forEach(t -> System.out.println(t)); // A classic lambda
    trees.forEach(System.out::println); // Method reference
    trees.forEach(Refs::print); // Refs is a our example class with its method
  }

  public static void print(String t) {
    System.out.println(t);
  }
}


There are also instance method references:

// A lambda:
p -> p.getName()

// Can become:
Potter::getName


I suggest you also read the following article, where we deepen the most used and generic functional interface categories:


That’s all with lambda expressions and functional interfaces.

Try it at home!

0
Be the first one to like this.
Please wait...

3 thoughts on...
  1. Asking questions are really fastidious thing if you are not understanding something fully, except this paragraph provides good understanding even. Lorie Johnny Dwan

  2. Really appreciate you sharing this blog post. Really looking forward to read more. Fantastic. Stephenie Gustavo Kampmann

Leave a Reply

Thanks for choosing to leave a comment.
Please keep in mind that all comments are moderated according to our comment policy, and your email address will NOT be published.
Please do NOT use keywords in the name field. Let's have a personal and meaningful conversation.