Reputation: 10639
Suppose I have a function with such signature:
public static <T> List<Future<T>> invokeAll(Stream<Callable<T>> tasks) {
... submit given tasks using executor ...
}
and I have a stream of data, which should be "wrapped" into callable and passed to this function. Naive mapping like below does not work:
Stream<String> ids = Stream.of("1", "2", "3");
invokeAll(ids.map((id) -> {
// Do a long computation with given ID...
return Boolean.TRUE; // Compilation error: Type mismatch: cannot convert from Boolean to Callable<Object>
}));
One solution would be to return lambda that returns lambda:
invokeAll(ids.map((id) -> {
return () -> {
// Do a long computation with given ID...
return Boolean.TRUE;
};
}));
another (in some way equivalent) is to use helper function:
public static <T> Callable<T> createCallable(T id) {
return () -> {
return id;
};
}
invokeAll(ids.map(ThisClass::createCallable));
but maybe there is better / shorter way of doing the same? E.g. somehow tell the compiler that it needs to create a Callable
that returns a given value:
invokeAll(ids.map((Function<String, Callable<Boolean>>) (id) -> {
// Do a long computation with given ID
return Boolean.TRUE;
}));
Thanks for any suggestion.
Upvotes: 1
Views: 383
Reputation: 44140
Let's ignore lambdas for a moment, because I think they're the source of the confusion. Let's use good old anonymous classes:
invokeAll(
ids.map(
new Function<String, Callable<Boolean>>()
{
@Override
public Callable<Boolean> apply(String str)
{
return new Callable<Boolean>()
{
@Override
public Boolean call() throws Exception
{
return Boolean.TRUE;
}
};
}
}
)
);
What you're effectively asking is "how I can automatically do this:"
invokeAll(
ids.map(
new Function<String, Callable<Boolean>>()
{
@Override
public Callable<Boolean> apply(String str)
{
return Boolean.TRUE;
}
}
)
);
Of course, you can't. A Boolean
is not a Callable<Boolean>
. So the solutions are limited to what you've already identified:
1) to use a lambda to create the Callable
:
() -> Boolean.TRUE
() -> { return Boolean.TRUE; }
2) to create a method which does this for you. Such as method is likely to more verbose than option #1 so it doesn't gain you anything.
Sorry, there's no way other to automagically make this any better.
Upvotes: 5