在字符串上应用JDK 8 Consumer

时间:2015-06-26 08:12:51

标签: java lambda java-8

我对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.acceptupper.apply的语法是唯一可能的语法,或者还有更多&#34; java 8 lambda&#34;我们可以写出最后两行的风格。

3 个答案:

答案 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接口:显式调用其方法。