// Lambda Expressions are, to put it simply, an easier way to create a // small class with only one function, as well as an instance of such // a class. Given some interface that contains *exactly* one function // declaration, such as: interface Intfun { int f(int x); } // We can implement the interface with a class and then create instances of // the class in the "standard" way: class Myownfun implements Intfun { public int f(int x) { return 2*x; } } // To use such a class I will need to create an instance of it: // Intfun N = new Myownfun(); // int result = N.f(2); // call function inside object. // However, in this case the class doesn't actually contain any data // (no instance variables, etc), and there is only one function. Notice // that for such classes, it doesn't matter how many instances you create. // In such situations, I can replace the cumbersome process of writing a // class and creating an instance with a "lambda expression": // Intfun N = (x) -> 2*x; // The line above is equivalent to writing a class and creating the instance // N separately. Java infers the type of x from the Intfun interface. // int result = N.f(2); // The lambda expression is called in the same way. public class lambdas { public static void main(String[] argv) { // Long way: create instances of Myownfun and then call function: Intfun F1 = new Myownfun(); System.out.println( F1.f(4) ); // prints 8 // Slightly better way: it's also possible to "inline" the // implementation of an interface: Intfun F2 = new Intfun() { public int f(int x) { return x*x; } }; System.out.println( F2.f(4) ); // prints 16 // Notice that the inlined definition creates a class "on the fly" PLUS // it also created an instance of the class, so there's no need to call new // With JDK 1.8, Java finally introduced Lambda Expressions, so the // above can be further simplified. Intfun F3 = (x) -> 2*x + 1; System.out.println( F3.f(4) ); // prints 9 // Java will infer that x is an int and that the expression is an // implementation of the function f with body { return 2*x+1; }. // Lambda expressions only work with interfaces that contain a SINGLE // declaration, as Intfun above. Many interfaces, such as Comparable // and Comparator, also contain single function declarations. // Here's another lambda expression. This time the lambda expression // requires the braces { } with the "return" keyword at the end: Intfun F4 = (int x) -> { System.out.println("this is an implementation of Intfun"); return (int)Math.pow(2,x); }; // use {} if expression requires multiple lines: note ; at end System.out.println( F4.f(8) ); // prints message, then prints 256 // The 'int' in '(int x)' is optional: Java infers that it must // be an int from the interface Intfun. // Lambda expressions with multiple arguments (Intfun2 defined below): Intfun2 morefun = (x,y) -> x*y; System.out.println( morefun.f(5,3) ); // prints 15 morefun = (x,y) -> x-y; // change the function System.out.println( morefun.f(5,3) ); // now prints 2 // Lambda expressions allows Java to be used as a "Functional // Programming Language", which means that functions can be treated // like any values. They can be assigned to variables, passed to // other functions, and even be returned by other functions. }//main }//main class interface Intfun2 { int f(int x, int y); } /* Advanced Notes: **Lack of Genuine Closures** The following code would NOT compile (if placed in main above): int y = 1; // local variable in main Intfun F5 = (x) -> { y++; // this line is not allowed return y+x; }; This lambda expression tries to change the local variable y each time it's called. For example, F5.f(1) will return 2 the first time it's called, 3 the second time, 4 the third time and so on. Java forces the variable y to be *finalized* when used in a lambda expression, so it cannot be changed. This feature is available in numerous other languages but is restricted in Java. However, it is easy to work around the restriction. You can refer to instance variables and static class variables and change them. For example, y can be declared as a static int y=1; outside of main. */