简体   繁体   English

在字符串上应用JDK 8 Consumer

[英]Apply JDK 8 Consumer on String

I have a question regarding Java 8. Here is my source code: 我有一个关于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();

This works quite well and produces following output: 这非常有效并产生以下输出:

HELLO 1
hello 2

My question is now if the syntax above d.accept and upper.apply is the only possible one or if there is some more "java 8 lambda" style we could write the last two lines. 我现在的问题是,如果d.acceptupper.apply上面的语法是唯一可能的语法,或者如果有更多的“java 8 lambda”样式,我们可以写出最后两行。

Before saying anything about about lambda expressions or functional interfaces, we have to talk about your really problematic mistake: you are calling run() on a thread! 在谈论lambda表达式或功能接口之前,我们必须讨论你真正有问题的错误: 在一个线程上 调用 run() If you want to start a new thread, you have to call start() on the Thread instance, if you want to run the code sequentially, don't create a Thread (but just a Runnable ). 如果要启动一个新线程,则必须在Thread实例上调用start() ,如果要按顺序运行代码,则不要创建一个Thread (但只是一个Runnable )。

That said, there are some default method on the functional interfaces of Java 8 for combining functions, eg you can chain two Function s via Function.andThen(…) but the available combinations are far away from being complete. 也就是说,Java 8的功能接口上有一些default方法用于组合函数,例如,您可以通过Function.andThen(…)链接两个Function但是可用的组合远远没有完成。

If a certain combining task repeats in your application, you may consider creating utility methods: 如果您的应用程序中重复某个组合任务,您可以考虑创建实用程序方法:

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();

But these three parts look more like a task for the stream API: 但这三个部分看起来更像是流API的任务:

Stream.of("Hello 1").map(upper).forEach(d);
Stream.of("Hello 2").map(lower).forEach(d);

I left the creation of the new thread out here, as it hasn't any benefit anyway. 我在这里留下了新线程的创建,因为它无论如何都没有任何好处。

If you really want parallel processing, you can do it on a per-character basis: 如果您真的想要并行处理,可以按字符进行:

"Hello 1".chars().parallel()
  .map(Character::toUpperCase).forEachOrdered(c->System.out.print((char)c));

but there still won't be any benefit given the simplicity of the task and the fixed overhead of the parallel processing. 但鉴于任务的简单性和并行处理的固定开销,仍然没有任何好处。

You can also write like this: 你也可以这样写:

    new Thread(() -> Stream.of("hello 1").map(upper).forEach(d)).run();
    new Thread(() -> Stream.of("hello 1").map(lower).forEach(d)).run();

Or more directlry: 或更直接的:

    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();

Yes, it's the only possible syntax. 是的,这是唯一可能的语法。 Actually when you use the lambda you don't even know whether it's actually lambda or just a plain old implementation of given interface (via anonymous class or even normal class). 实际上当你使用lambda时,你甚至不知道它实际上是lambda还是只是一个给定接口的普通旧实现(通过匿名类甚至普通类)。 So you have to use functional interface as any other Java interface: call its method explicitly. 因此,您必须使用功能接口作为任何其他Java接口:显式调用其方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM