用更少的努力在java流中重写算法?

Nic*_*cky 5 java arrays function java-8 java-stream

我正在学习 Java 8 中的 Streams。

例如,如果我必须将一个数字加倍:

Arrays.stream(intArray).map(e->e*2).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

如果我必须对一个数字进行平方,那么我可以在下面使用:

Arrays.stream(intArray).map(e->e*e).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

但是,如果我必须使用"andThen"method在同一个 Integer 数组上应用这两个函数java.util.function.Function,我将通过以下方式进行:

  Function<Integer, Integer> times2 = e -> e * 2;

  Function<Integer, Integer> squared = e -> e * e;  

 Arrays.stream(intArray).map(times2.andThen(squared)).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

是否可以在单行中重写此(3 个语句),例如:

Arrays.stream(intArray).map(e->e*2.andThen(f->f*f)).forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

这给了我一个编译器错误。有可能做到吗?

tso*_*akp 4

看起来 Java 并没有隐式地假定 lambda 表达式是特定的函数类型。我必须添加强制转换才能使其正常工作:

Arrays.stream( new int[]{ 1, 2, 3, 4 } )
.map( ( (IntUnaryOperator)( e -> e*2 ) ).andThen(f->f*f) )
.forEach(System.out::println);
Run Code Online (Sandbox Code Playgroud)

我个人不喜欢这个,更喜欢使用双地图调用。我很想看到更好的主意。

  • Lambda 表达式没有内在类型;它们需要_目标类型_(必须是_功能接口_)。相同的 lambda 表达式可以与许多功能接口兼容;`s -&gt; s.isEmpty()` 可以是 `Function&lt;String, Boolean&gt;` 或 `Predicate&lt;String&gt;`。您需要提供一些类型信息;类型推理!=读心术。 (3认同)
  • 问题在于链接。如果您提供单个 lambda 作为“map()”的参数,它将完全按照您的预期工作。但对于链式表达式,它只能推断链式表达式 `e-&gt;e*2.andThen(f-&gt;f*f)` 是一个 `IntUnaryOperator`。但是,`e-&gt;e*2` 的类型是什么?它不知道。编译器可以派生的唯一约束是它是具有名为“andThen()”方法的某种类型。 (2认同)
  • 它对 `.map(times2.andThen(e -&gt; e*e))` 也没有问题,因为它知道 `times2` 的类型。 (2认同)
  • 不。你要求读心术,基于你现在脑海中碰巧想到的一个例子。有无限多种可能的函数接口类型,它们可能具有名为“andThen()”的方法,该方法可以具有任意签名。它有什么可能的理由假设它是“IntUnaryOperator”,而不是其他东西? (2认同)
  • 抱歉,这纯粹是一厢情愿的想法(主要是因为脑子里只有一个例子。)这实际上只是要求编译器进行疯狂的猜测,因为它在附近的某个地方看到了该类型。但没有可信的理由来猜测这种类型,而且人们可以很容易地构造出这种猜测是错误的示例。这不是设计语言的方式。 (2认同)