【问题标题】:How to force an immediate evaluation on stream in Java8如何在 Java8 中强制对流进行立即评估
【发布时间】:2016-02-01 22:19:33
【问题描述】:

我想知道如何强制对 Java8 中的每个地图函数进行立即评估?我现在的情况是我需要进行多级转换(从 ObjectA -> ObjectB -> ObjectC -> ObjectD),并且对于某些对象,在此转换的每个级别上都可能出现失败(抛出异常)。例如

 // stream -> map -> collect sequence
 lists.stream()
      .map(aToB)
      .collect(Collectors.toList())
      .stream()
      .map(bToC)
      .collect(Collectors.toList())
      .stream()
      .map(cToD)
      .collect(Collectors.toList())

 // Try api is from javaslangs
 Function<ObjectA, ObjectB> aToB = a -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

 Function<ObjectB, ObjectC> bToC = b -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

 Function<ObjectC, ObjectD> cToD = c -> Try.of(() -> .....)
                                           .onFailure(....)
                                           .get();

我想测试我的单元测试中的每个转换,例如测试测试是否抛出异常,以及如果在将 A 转换为 B 时出现异常时 A 未成功转换为 C 类似的东西,但是通过惰性评估,这变成无法测试,我能想到的唯一方法是执行此steam() -&gt; map(...) -&gt; collect(...) 调用序列以强制立即评估。我想知道有没有更好的方法来写这个。

【问题讨论】:

  • 为什么?将所有 map 链接起来有什么问题?
  • 我不明白这个问题。当您收集最终结果时,所有函数都已应用于所有流元素,或者,如果任何评估失败,异常将传播给调用者,因此您已经测试了所有函数。如果出现异常,堆栈跟踪会告诉您哪个函数失败了。那么你想用这些中间的.collect(Collectors.toList()).stream() 解决什么样的问题呢?除了性能之外,它们不会改变任何东西。
  • 每种情况下是抛出不同的异常,还是同一个异常?
  • 如果你想要N个单独的评估,写N个流管道,并在每个之后立即测试结果。试图用一种大表情来做这件事只会分散注意力。

标签: java lambda functional-programming java-8 java-stream


【解决方案1】:

这里有一些简单的想法:

  • 在单元素集合上测试整个流式操作链。验证是否在您期望的地方引发了异常。
  • 不用担心测试流框架;只需自己在测试中直接应用函数,而不是通过流。

一般来说,不要试图在测试中处理惰性求值:测试函数,并相信流框架在真实代码中做正确的事情。

【讨论】:

  • 你的意思是单独和独立地为 a->b、b->c 和 c->d 编写测试,而不是作为一个整体而不是 a->b->c->d?
  • @peter 当然,或两者兼而有之,但主要测试单个元素而不是元素流。
  • 只是为了看看我是否做对了......所以在我的测试中我会手动进行这个立即评估......但在开发中我应该相信它是lists.stream()。 map(aToB).map(bToC).map(cToD).collect(...) 这样?
  • @peter,是的,就是这样。
【解决方案2】:

您可以编写一个静态帮助器方法,将收集到一个集合中,然后返回该集合的流,并将流管道的各个步骤包装到该帮助器中。

您应该知道这会改变流的语义。

例如,如果在这种情况下处理无限流源可能会失败,即使如果通过短路操作终止完整的流管道可能会成功。类似地,并行性和并发属性可能会改变。因此,您最终会测试与流管道本身不同的东西。

相反,最好只测试完整的流管道,以便为可能的输入场景提供预期的输出,并可能在各种输入上分别测试映射函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-19
    • 2017-07-31
    相关资源
    最近更新 更多