What's new in JDK 8? - Lambda Expressions

Lambda Expressions is an addition to Java which has caught everyone's attention. It is an interesting addition which will make code look cleaner and a bit smaller. To sum it up in one sentence - Lambda Expressions are a short-cut for implementing function interfaces.

What is a function interface?

A functional interface is an interface which has only one abstract method. Some common examples are Runnable, ActionListener etc.

How we used them earlier?

  • By implementing it to a Class.
    class FunctionalInterface1 implements Runnable {
      @Override
      public void run() {
        System.out.println("Hello from Thread!");
      }
      public void startThread() {
        Thread thread=new Thread(this);
        thread.start();
      }
      public static void main(String[] args) {
        new FunctionalInterface1().startThread(); 
      }
    }
  • By using Anonymous Classes.
    class FunctionalInterface2 {
      public void startThread() {
        Thread thread=new Thread(new Runnable() {
          @Override
          public void run() {
            System.out.println("Hello from Anonymous Class!");
          }
        });
        thread.start();
      }
      public static void main(String[] args) {
        new FunctionalInterface2().startThread(); 
      }
    }

How to use Lamda Expressions?

Lambda Expressions have now made life easier by reducing by reducing it to a single line process. Here we go:

class LambdaTest {
  public static void main(String args[]) {
    Runnable r = () -> System.out.println("Hello from Lambda!");
    r.run();
  }
}

Just that much? Yes. Because a functional interfaces just has one abstract function, the () in the above code refers to the same function, run() in the case of Runnable.

The syntax of a Lambda Expression is

(args) -> Statement(s);

So, now you don't need to write tedious Anonymous classes for button ActionListener. You can simply write

JButton button=new JButton("Lambda");
button.addActionListener((e) -> System.out.println("Action Performed!"));

or to sort arrays in alphabetical order for instance

String[] array = {"abc","fatir","abdul","hello"};
java.util.Arrays.sort(array, (s1,s2) -> s1.compareTo(s2));

Yes, you don't need to even mention the type of e (ActionEvent) in the expression, JDK 8 understands it all.

In the following example I give examples of custom functional interfaces

interface OneOperandFunction {
  public double compute(double a);
}
interface TwoOperandFunction {
  public double compute(double a, double b);
}
public class CustomLambdas {
  public static void main(String args[]) {
    double x = 0.9, y = 56.8;
    // No need to use return if you use no braces.
    OneOperandFunction cube = a -> a*a*a; 
    // Use braces for multi-line Lambdas with a return statement
    TwoOperandFunction expression = (a,b) -> {
      double c = a*a;
      double d = b-10;
      return c*d;
    };
    System.out.println(cube.compute(x));
    System.out.println(expression.compute(x,y));
  }
}

The above code has two functional interfaces OneOperandFunction and TwoOperandFunction. The first one performs operations on one operand and the second one does the same on two operands.

You however won't create any new functional interfaces because JDK8 has made a lot of templates for you in the java.util.function package. A few of them are

  • Consumer<T> - Represents an operation that accepts a single input argument and returns no result.
  • Function<T,R> - Represents a function that accepts one argument and produces a result.
  • Predicate<T> - Represents a predicate (boolean-valued function) of one argument.4) Supplier<T> - Represents a supplier of results.
  • UnaryOperator<T> - Represents an operation on a single operand that produces a result of the same type as its operand. 6) BinaryOperator<T> - Represents an operation upon two operands of the same type, producing a result of the same type as the operands.
  • and many more.

Further Reading