看这个问题:如何在Java8中动态做过滤?
问题是在执行过滤器后截断流。我不能使用限制,因为我不知道过滤后的列表有多长。那么,我们可以计算过滤后的元素数吗?
所以,我想我可以创建一个类,计算并通过地图传递流。代码在这个答案中。
我创建了一个可计数的类,但保持元素不变,我在这里使用了一个函数,以避免使用我在另一个答案中使用的lambdas:
class DoNothingButCount<T > implements Function<T, T> {
AtomicInteger i;
public DoNothingButCount() {
i = new AtomicInteger(0);
}
public T apply(T p) {
i.incrementAndGet();
return p;
}
}
所以我的流最终是:
persons.stream()
.filter(u -> u.size > 12)
.filter(u -> u.weitght > 12)
.map(counter)
.sorted((p1, p2) -> p1.age - p2.age)
.collect(Collectors.toList())
.stream()
.limit((int) (counter.i.intValue() * 0.5))
.sorted((p1, p2) -> p2.length - p1.length)
.limit((int) (counter.i.intValue() * 0.5 * 0.2)).forEach((p) -> System.out.println(p));
但我的问题是关于我的例子的另一部分。
collect(Collectors.toList()).stream().
如果我删除这一行,结果是当我试图执行limit时,计数器为零。不知何故,我通过使用一个可变对象欺骗了“efectively final”的要求。
我可能是错的,但是我明白流是首先构建的,所以如果我们使用可变对象将参数传递给流中的任何步骤,这些参数将在流创建时被采用。
我的问题是,如果我的假设是正确的,为什么需要这样做?流(如果非并行)可以依次通过所有步骤(过滤器、map...),所以不需要这个限制。
我的问题是,如果我的假设是正确的,为什么需要这个?流(如果不平行)可以顺序通过所有步骤(过滤,映射..)所以不需要这个限制。
正如您已经知道的,对于并行流,这听起来很明显:需要这种限制,因为否则结果将是不确定性的。
对于非并行流,由于其当前的设计,这是不可能的:每个项目只访问一次。如果流按照您的建议工作,它们将在进入下一步之前对整个集合执行每一步,我认为这可能会对性能产生影响。我怀疑这就是语言设计师做出这个决定的原因。
你已经知道这一点,但下面是对其他读者的解释。从文件中:
流是懒惰的;源数据的计算仅在启动终端操作时执行,源元素仅在需要时使用。
< code>Stream的每个中间操作,如< code>filter()或< code>limit()实际上只是某种初始化流选项的setter。
当您调用终端操作(如 forEach()
、collect()
或 count())时
,就是计算发生的时候,按照先前构建的管道处理项目。
这就是为什么 limit()
的参数在单个项目完成流的第一步之前被计算出来的原因。这就是为什么您需要使用终端操作结束流,然后使用您将知道的 limit()
开始一个新的流。
让您的流管道成为步骤X
我们希望并行处理我们的项目。因此,如果我们允许步骤Y的行为依赖于已经通过X的项目,那么Y是不确定的。这是因为在项目到达步骤Y的那一刻,已经通过X的项目集合在多次执行中不会相同(因为线程)。
根据定义,流用于处理流程中的项目。你可以把一个非并行流想象成这样:一个单独的项目通过所有的步骤,然后下一个项目通过所有的步骤,等等。事实上,医生说了一切:
流的元素在流的生命周期内仅访问一次。像迭代器一样,必须生成一个新的流来重新访问源的相同元素。
如果流不是这样工作的,那么在进入下一步之前,只对整个集合执行每一步也不会比这更好。这实际上允许在非并行流中使用可变参数,但可能会对性能产生影响(因为我们会在集合上迭代多次)。无论如何,他们目前的行为不允许你想要的。
如果我的API提供了一个流,客户端是否有办法修改基础集合? 例如: 客户端是否可以调用并以某种方式修改的内容?
我正在寻找一种方法来调用多个参数方法,但是使用构造。文档中说只有在能够映射到功能接口时才可用。 基本上,如上所述,考虑使用中不同数量的属性的方法。
只是在列表下面迭代 以上三个迭代有什么区别
我正在解析输入JSON。对于一个字段,有3种可能: 字段不存在; 该值设置为NULL; 该值设置为有效值。 null
5.7. 可变参数 参数数量可变的函数称为为可变参数函数。典型的例子就是fmt.Printf和类似函数。Printf首先接收一个的必备参数,之后接收任意个数的后续参数。 在声明可变参数函数时,需要在参数列表的最后一个参数类型之前加上省略符号“...”,这表示该函数会接收任意数量的该类型参数。 gopl.io/ch5/sum func sum(vals...int) int { total
问题内容: 我正在尝试创建一个字符串扩展来做类似的事情 看起来像这样 它给我以下编译错误 类型CVaListPointer不符合协议CVargType 有人知道如何解决此编译错误吗? 问题答案: 这应该非常简单,只需更改您的参数,如下所示: 初始化(格式:语言环境:参数:)