当前位置: 首页 > 知识库问答 >
问题:

有条件地向Java8流添加一个操作

梁华清
2023-03-14
// Do some stream stuff
stream = stream.filter(e -> e.getTimestamp() < max);

// Limit the stream
if (limit != -1) {
   stream = stream.limit(limit);
}

// Collect stream to list
stream.collect(Collectors.toList());

正如这篇stackoverflow文章中所述,在调用终端操作之前,不会实际应用筛选器。既然我在调用终端操作之前重新分配了stream的值,那么上面的代码是否仍然是使用Java8流的适当方法呢?

共有1个答案

沈思博
2023-03-14

链接的一系列调用与存储中间返回值的一系列调用之间没有语义差异。因此,以下代码片段是等价的:

a = object.foo();
b = a.bar();
c = b.baz();

而且

c = object.foo().bar().baz();

在这两种情况下,每个方法都是根据前一次调用的结果调用的。但在后一种情况下,中间结果不会存储,而是在下一次调用时丢失。对于stream API,在对其调用下一个方法之后,不能使用中间结果,因此链接是使用stream的自然方式,因为它在本质上确保了不会对返回的引用调用多个方法。

try(Stream<String> stream = Files.lines(Paths.get("myFile.txt"))) {
    stream.filter(s -> !s.isEmpty()).forEach(System.out::println);
}
try(Stream<String> stream = Files.lines(Paths.get("myFile.txt")).filter(s->!s.isEmpty())) {
    stream.forEach(System.out::println);
}

而且

try(Stream<String> srcStream = Files.lines(Paths.get("myFile.txt"))) {
    Stream<String> tmp = srcStream.filter(s -> !s.isEmpty());
    // must not be use variable srcStream here:
    tmp.forEach(System.out::println);
}

它们是等价的,因为foreach总是在filter的结果上调用,而filter.lines的结果总是在files.lines的结果上调用,最后的close()操作在哪个结果上调用并不重要,因为关闭会影响整个流管道。

用一句话来说,你使用它的方式,是正确的。

我甚至更喜欢这样做,因为当您不想应用限制时,不链接limit操作是表达您的意图的最干净的方式。还值得注意的是,建议的替代方案在很多情况下都可以工作,但它们在语义上并不等价:

.limit(condithtml" target="_blank">ion? aLimit: Long.MAX_VALUE)

假设您所能遇到的元素的最大数量是long.max_value,但是流可以有更多的元素,它们甚至可能是无限的。

.limit(condition? aLimit: list.size())

当流源是list时,将打破流的惰性计算。原则上,可变流源可以合法地被任意更改,直到终端操作开始时为止。结果将反映到目前为止所做的所有修改。当您添加包含list.size()的中间操作(即此时列表的实际大小)时,在此点和终端操作之间应用于集合的后续修改可能会使该值具有不同于预期的“实际上没有限制”语义的含义。

请参阅API文档中的“无干扰”部分:

对于行为良好的流源,可以在终端操作开始之前修改源,这些修改将反映在覆盖的元素中。例如,请考虑以下代码:

List<String> l = new ArrayList(Arrays.asList("one", "two"));
Stream<String> sl = l.stream();
l.add("three");
String s = sl.collect(joining(" "));

首先创建一个由两个字符串组成的列表:“one”;和“二”。然后从该列表创建一个流。接下来,通过添加第三个字符串来修改列表:“three”。最后,流的元素被收集并连接在一起。由于列表是在终端收集操作开始之前修改的,因此结果将是一个“One two Three”字符串。

 类似资料:
  • 是否有一种方法可以使用单个流来实现? 用两个独立的流很容易做到这一点,但我不能只用一个。

  • 我可以添加流或额外的元素,像这样: 我可以边走边添加新的东西,比如: 但这很难看,因为是静态的。如果是一个实例方法,那么上面的示例将更容易阅读: 而且 2)无论如何,有没有更好的方法?

  • 我试图翻译这个(简化)代码使用Java-8流: 以下是我尝试过的: 但以上给出了所有

  • 问题内容: 如果满足特定条件,是否有办法仅向React组件添加属性? 我应该在渲染后基于Ajax调用将required和readOnly属性添加到表单元素中,但是由于readOnly =“ false”与完全省略该属性不同,因此我看不到如何解决此问题。 下面的示例应解释我想要的内容,但将无法正常工作(解析错误:意外的标识符)。 问题答案: 显然,对于某些属性,如果您传递给它的值不真实,React足

  • 我想有条件地向对象添加一个属性。目前我有这个: 问题是如果汽车。电池不存在我有电池:未定义。如果对象中不存在该属性,我宁愿不要该属性。我怎样才能做到这一点?

  • 我正在尝试执行以下操作以满足代码构建器的要求(具体来说是Sencha Cmd)。 这是我需要做的本质。关键因素是函数体必须以返回对象文字结束。由于生成器中的限制,我无法返回变量。那么,如果参数includeB为true,如何在下面的伪代码点添加属性“b”,但如果为false,则根本不添加属性。不允许ie b==未定义或b==null。 也许这是不可能的。 感谢阅读和考虑, 默里