我对Java 8有疑问。这是我的源代码:
final Consumer<String> d = e -> System.out.println(e);
final Function<String, String> upper = x -> x.toUpperCase();
final Function<String, String> lower = x -> x.toLowerCase();
new Thread(() -> d.accept(upper.apply("hello 1"))).run();
new Thread(() -> d.accept(lower.apply("hello 2"))).run();
这非常有效并产生以下输出:
HELLO 1
hello 2
现在我的问题是,如果上面d.accept
和upper.apply
的语法是唯一可能的语法,或者还有更多&#34; java 8 lambda&#34;我们可以写出最后两行的风格。
答案 0 :(得分:9)
在谈论lambda表达式或功能接口之前,我们必须讨论你真正有问题的错误:你在一个线程上调用 run()
!如果要启动新线程,则必须在start()
实例上调用Thread
,如果要按顺序运行代码,请不要创建Thread
(但只需要Runnable
)。
也就是说,Java 8的功能接口上有一些default
方法用于组合函数,例如:您可以通过Function.andThen(…)
链接两个Function
,但可用的组合远未完成。
如果您的应用程序中重复某个组合任务,您可以考虑创建实用程序方法:
public static <T> Runnable bind(T value, Consumer<T> c) {
return ()->c.accept(value);
}
public static <T,U> Consumer<U> compose(Function<U,T> f, Consumer<? super T> c) {
return u->c.accept(f.apply(u));
}
new Thread(bind("Hello 1", compose(upper, d))).start();
new Thread(bind("Hello 2", compose(lower, d))).start();
但这三个部分看起来更像是流API的任务:
Stream.of("Hello 1").map(upper).forEach(d);
Stream.of("Hello 2").map(lower).forEach(d);
我在这里留下了新线程的创建,因为它无论如何都没有任何好处。
如果您真的想要并行处理,可以按字符进行:
"Hello 1".chars().parallel()
.map(Character::toUpperCase).forEachOrdered(c->System.out.print((char)c));
但鉴于任务的简单性和并行处理的固定开销,仍然没有任何好处。
答案 1 :(得分:5)
您也可以这样写:
new Thread(() -> Stream.of("hello 1").map(upper).forEach(d)).run();
new Thread(() -> Stream.of("hello 1").map(lower).forEach(d)).run();
或更直接:
new Thread(() -> Stream.of("hello 1").map(String::toUpperCase).forEach(System.out::println)).run();
new Thread(() -> Stream.of("hello 1").map(String::toLowerCase).forEach(System.out::println)).run();
答案 2 :(得分:3)
是的,这是唯一可能的语法。实际上当你使用lambda时,你甚至不知道它实际上是lambda还是只是一个给定接口的普通旧实现(通过匿名类甚至普通类)。因此,您必须使用功能接口作为任何其他Java接口:显式调用其方法。