11

As I know, there are 3 kinds of java lambda expressions.

  1. (int x, int y) -> { return x + y; }
  2. x -> x * x
  3. ( ) -> x

The third one seems never ever used.

Could you give an example for each of the 3 cases (an extra example for case 3 will be good) to illustrate their usage? Please make them as simple as possible (preferably starting with list.stream()....)

3
  • 1
    The third one seems never used??? I just used it here: stackoverflow.com/questions/40797960/chicken-egg-lifecycle Commented Nov 26, 2016 at 4:53
  • 1
    Supplier<Integer> sup = () -> 2; Commented Nov 26, 2016 at 12:13
  • 3
    These aren't different "kinds" of lambda expressions (and you've not even exhaustively covered the options). The third is merely a special case of the first, where there are simply zero arguments. The second is a special syntactic form, where you can omit the parentheses if there is exactly one argument and you've chosen to let the compiler infer the argument types. You can also choose to let the compiler infer all the argument types, in which case you'd get something like (x,y,z) -> x+y+z. But they're all the same "kind" of thing. Commented Nov 26, 2016 at 21:16

3 Answers 3

9
  1. The first expression will be used where you get 2 parameters for a method and return a value.

  2. The second expression will be used x -> x * x where you get 1 parameters for a method and return a value.

  3. The third expression ( ) -> x will be used ( ) -> x where you get 0 parameters for a method and return a value.

Let's take the third one. Suppose you have an interface which takes no parameters and returns a value.

static interface RandomMath {
    public int random();
}

Now You want to instantiate this interface along with its implementation. Without using lambda it will be done as below:-

Random random = new Random();
RandomMath randomMath = new RandomMath() {
    @Override
    public int random() {
        return random.nextInt();
    }
};

Using lambda it will be like:-

Random random = new Random();
RandomMath randomMath = () -> random.nextInt(); //the third type.

Similarly, for first two it can be used for methods which take two and one parameters and return a value.

static interface PlusMath {
    public int plus(int a, int b);
}

PlusMath plusMath = (a, b) -> a + b;

static interface SquareMath {
    public int square(int a);
}

SquareMath squareMath = a -> a * a;
Sign up to request clarification or add additional context in comments.

Comments

5

The first two examples are different from the last one. The variables in the function (lambda expression) refer to its parameters.

While in the third example the x refers to variable outside of the lambda expression but within the lexical scope (can be either local variable from the method or instance variable).

Example 1 (typically stream reduce), computes the sum by passing the so far computed sum and next item from the list to lambda function:

 int sum = list.stream().reduce((int x, int y) -> x+y);

Example 2, computes the squares from the elements:

 squares = list.stream().map((int x) -> x*x).collect(Collectors.toList());

Example 3, sets the element to default value if it's null in the list:

 final int x = MY_DEFAULT_VALUE;
 // lambda refers the the variable above to get the default
 defaults = list.stream().map((Integer v) -> v != null ? v : x);

Or better for example 3 is the map atomic methods:

 int x = MY_DEFAULT_VALUE;
 // lambda refers the the variable above to get the default
 map.computeIfAbsent(1, (Integer key) -> x);
 // the same could be achieved by putIfAbsent() of course
 // but typically you would use (Integer key) -> expensiveComputeOfValue(x)
 // ...
 // or quite common example with executor
 public Future<Integer> computeAsync(final int value) {
     // pass the callback which computes the result synchronously, to Executor.submit()
     // the callback refers to parameter "value"
     return executor.submit(() -> computeSync(value));
 }

Comments

4

Before going through the below examples, first, note that Lambda expressions can be written for any SAM (also called Functional) interfaces (Infact, Lambda expression is a syntactic sugar for replacing the verbose anonymous class (with single method) in Java).

Single Abstract Method interface or Functional Interface is an interface which contains only one abstract method), you can look here. If you know this simple point, you can write (play with) any number of your own Functional interfaces and then write the different Lambda Expressions according to each of those the Functional interface methods.

Below examples have been written by making use of the existing JDK (1.8) Functional interfaces like Callable, Function, BiFunction (Like these, there are many in built Functional interfaces in JDK 1.8, most of the times they readily suit our requirements).

(1) Example for (int x, int y) -> { return x + y; }

//Below Lamda exp, takes 2 Input int Arguments and returns string
BiFunction<Integer, Integer, String> biFunction = (num1, num2) -> 
               "Sum Is:" +(num1 + num2);
System.out.println(biFunction.apply(100, 200));

(2) Example for x -> x * x

//Below Lamda exp, takes string Input Argument and returns string
list.stream().map((String str1) -> 
       str1.substring(0, 1)). 
           forEach(System.out::println);    

(3) Example for () -> x

//Below Lambda exp, Input argument is void, returns String
Callable<String> callabl = () -> "My Callable";
ExecutorService service =  Executors.newSingleThreadExecutor();
Future<String> future = service.submit(callable);
System.out.println(future.get());

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.