Reputation: 5680
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
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
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