在Stream.map()中将Consumer转换为Runnable

Nat*_*han 4 java eclipse java-stream functional-interface

我正在尝试将a转换Consumer为a Runnable.下面的代码并不会产生在Eclipse IDE中任何编译器错误.

Consumer<Object> consumer;
Runnable runnable;
Object value;

...
runnable = () -> consumer.accept(value);
Run Code Online (Sandbox Code Playgroud)

以下代码在Eclipse IDE中生成编译器错误.

ArrayList<Consumer<Object>> list;
Object value;

...

list.
   stream().
   map(consumer -> () -> consumer.accept(value));
Run Code Online (Sandbox Code Playgroud)

错误是:

Type mismatch: Can not convert from Stream<Object> to <unknown>.
The target type of this expression must be a functional interface.
Run Code Online (Sandbox Code Playgroud)

我如何帮助编译器将a转换ConsumerRunnable

以下代码修复了该问题,但非常详细.

map(consumer -> (Runnable) (() -> consumer.accept(value)));
Run Code Online (Sandbox Code Playgroud)

有没有更简洁的方法来做到这一点?我知道我可以创建一个接受a Consumer并返回a 的静态方法Runnable,但我不认为这更简洁.

Tun*_*aki 12

如果您考虑表达式,则错误消息是正常的:

list.stream().map(consumer -> () -> consumer.accept(value))
                              ^--------------------------^
                                what is the type of that?
Run Code Online (Sandbox Code Playgroud)

问题是编译器无法确定表达式的目标类型() -> consumer.accept(value).它当然可以Runnable,但它也可以MyAwesomeInterface声明:

@FunctionalInterface
interface MyAwesomeInterface { void foo(); }
Run Code Online (Sandbox Code Playgroud)

实际上,它可以符合任何声明函数方法的函数接口,该函数方法不带参数并且不返回任何值.因此,这会导致编译错误.

将lambda表达式显式存储在Runnablewith中时没有错误:

Runnable runnable = () -> consumer.accept(value);
Run Code Online (Sandbox Code Playgroud)

因为,然后编译器知道该lambda的目标类型是Runnable.


当你考虑时,问题更加模糊:

List<Runnable> runnables = list.stream()
                               .map(consumer -> () -> consumer.accept(value))
                               .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

有人可能会争辩说,编译器可能能够推断出该表达式的目标类型,Runnable因为我们正在将其收集到列表中Runnable.但是,它没有,你必须帮助编译器一点点,并明确告诉编译器Stream元素是Runnable:

List<Runnable> runnables = list.stream()
                               .<Runnable> map(consumer -> () -> consumer.accept(value))
                               .collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)