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

时间:2016-02-18 18:50:11

标签: java eclipse java-stream functional-interface

我正在尝试将Consumer转换为Runnable。以下代码在Eclipse IDE中生成任何编译器错误。

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

...
runnable = () -> consumer.accept(value);

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

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

...

list.
   stream().
   map(consumer -> () -> consumer.accept(value));

错误是:

Type mismatch: Can not convert from Stream<Object> to <unknown>.
The target type of this expression must be a functional interface.

如何帮助编译器将Consumer转换为Runnable

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

map(consumer -> (Runnable) (() -> consumer.accept(value)));

有更简洁的方法吗?我知道我可以创建一个接受Consumer并返回Runnable的静态方法,但我并不认为这更简洁。

1 个答案:

答案 0 :(得分:10)

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

list.stream().map(consumer -> () -> consumer.accept(value))
                              ^--------------------------^
                                what is the type of that?

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

MyAwesomeInterface

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

使用:

@FunctionalInterface interface MyAwesomeInterface { void foo(); } 中显式存储lambda表达式时没有错误
Runnable

因为,然后编译器知道该lambda的目标类型是Runnable runnable = () -> consumer.accept(value);

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

Runnable

有人可能会争辩说,编译器可能能够将该表达式的目标类型推断为List<Runnable> runnables = list.stream() .map(consumer -> () -> consumer.accept(value)) .collect(Collectors.toList()); ,因为我们将其收集到Runnable列表中。但是,it doesn't并且您必须帮助编译器稍微明确地告诉编译器Runnable元素是Stream

Runnable