nimo23
nimo23

Reputation: 5680

Shorten nested lambda

I want to map a list of tasks to List<Callable<Tasks>>:

List<Callable<Tasks>> callableTasks = tasks.stream().map(t ->
        {
            // how to return callable directly and omitting curly braces?
            Callable<Task> task = () -> run(t);
            return task;
        }).collect(Collectors.toList());

How can I shorten the above expression to return the callable directly?

Upvotes: 0

Views: 101

Answers (2)

Holger
Holger

Reputation: 298123

The problem is that the lambda expression () -> run(t) requires a target type.

In a construct like

List<Callable<Tasks>> callableTasks = tasks.stream()
    .map(…).collect(Collectors.toList());

The assignment to List<Callable<Tasks>> callableTasks provides a target type to the collect method invocation, but can’t propagate it to the preceding map invocation (a general limitation of Java’s current type inference).

By splitting the mapping function into an assignment and a return statement, you are providing a target type. Likewise, you could provide target type by casting, e.g. .map(t -> (Callable<Task>)() -> run(t)) or by providing an explicit type for the generic method map, e.g. .<Callable<Task>>map(t -> () -> run(t)).

The latter solution leads to

List<Callable<Task>> callableTasks = tasks.stream()
    .<Callable<Task>>map(t -> () -> run(t)).collect(Collectors.toList());

If the Task instance returned by run(t) is the same as passed to it as argument, you can use Executors.callable like:

List<Callable<Task>> callableTasks = tasks.stream()
    .map(t -> Executors.callable(() -> run(t), t)).collect(Collectors.toList());

Note the Executors.callable encapsulates a Runnable, which provides no return value. So the constructed Callable will evaluate to the result specified to Executors.callable as second argument or to null if you use the one argument version.

Upvotes: 3

Andronicus
Andronicus

Reputation: 26036

You can use static methods from Executors class, for example Executors.callable:

tasks.stream().map(t -> callable(() -> run(t))).collect(Collectors.toList());

Upvotes: 4

Related Questions