Lambdas

In Java, lambdas are supported as syntactic sugar over interfaces with a single unimplemented method (Java 8 allows to provide default implementation).

When lambda has one argument, parentheses may be omitted: i -> {}.

The return statement can be omitted when lambda only return single expression: (i, j) -> i+j.

A lambda can capture variables from outside the lambda body. This include local variables, static and object fields.

/* ([<param1> [,<paramn>]]) -> {
  // code to be executed
}*/

public class Demo {
    interface Listener {
        void onEvent(Demo demo); // abstract method
    }
    
    // method reference is used to initiate a variable
    //private Listener listener = this::defOnEvent;
    
    // lambda is used to initiate a variable
    private Listener listener = m -> System.out.println("listener called");
    
    public void setListener(Listener l) {
        listener = l == null ? this::defOnEvent : l;
    }

    private void defOnEvent(Demo m){
        
    }
    
    public static void main(String[] args) {
        Demo demo = new Demo();
        demo.setListener((a)->{/*...*/});
        demo.listener.onEvent(demo);
        demo.setListener(demo::defOnEvent);
        
        int g=100;
        BiFunction<Integer, Integer, String> 
            a = (i1,i2) -> "(" + i1 + " + "+ i2 + ")-" + g;
        String str = a.apply(23,32);
    }
}

method reference

Lambda may be replaced by method reference. Obviously lambda and method must have same signature.

reader.lines().forEach(System.out::println);
// same as
 reader.lines().forEach(s -> System.out.println(s));

functional interfaces

Java has predefined built-in interfaces in java.util.function package such Function. These functional interfaces useful when working with lambdas.

// without lambda syntax  
interface MyStringFactory {
    String newString(int seed);
}
    
MyStringFactory factory1 = new MyStringFactory() {

    @Override
    public String newString(int seed) {
        return "("+seed+")";
    }
};
    
// with lambda syntax    
IntFunction<String> factory2 = seed -> "("+seed+")";

@FunctionalInterface annotation

The @FunctionalInterface annotation protects your interface from adding new abstract method. It is useful when you want to instantiate interface by lambda.

// from Java source
@FunctionalInterface
public interface Runnable {
    public abstract void run();
}