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

在执行其他操作之前查找流大小

王刚毅
2023-03-14

在我的程序中,我反复1收集Java8流,以将对象集合减少为单个对象。在整个执行过程中,这个集合的大小可能会有很大的变化:从3个对象到数百个对象。

public void findInterestingFoo(Stream<Foo> foos) {
    internalState.update(foos.collect(customCollector()));
}

在优化我的代码和搜索瓶颈的过程中,我在某个点使流并行。这在当时起了作用,因为所有的收藏都相当大。后来,在更改程序的其他部分和参数后,集合变小了。我意识到不让流平行更有效。这是有道理的:为4个对象在多个线程上分配工作的开销根本不值得。不过,对于成百上千的物体来说,这是值得的。

如果我能只让大的溪流平行,那就真的很方便了:

public void findInterestingFoo(Stream<Foo> foos) {
    if (isSmall(foos)) {
        internalState.update(foos.collect(customCollector()));
    } else {
        internalState.update(foos.parallel().collect(customCollector()));
    }
}

当然,当从数组、集合或手动创建流时,可以手动执行此操作。也就是说,我们知道流中的元素,所以这是可以跟踪的。然而,我感兴趣的是以一种通用的方式解决这一问题,这样,无论将哪种流传递给findinterestingfoo,它都能得到适当和尽可能有效的处理。

    null

不过,我想知道在对流执行任何操作之前,是否有任何方法可以确定流中有多少元素。流真的不知道它是从有限集合创建的吗?

________
1数千次。在我的例子中,对此进行优化可使总运行时间从1.5秒提高到0.5秒。

共有1个答案

微生翼
2023-03-14

理论上,您可以这样做:

public void findInterestingFoo(Stream<Foo> foos) {
    Spliterator<Foo> sp = foos.spliterator();
    long size = sp.getExactSizeIfKnown();// returns -1 if not known
          // or sp.estimateSize(); // Long.MAX_VALUE means "unknown"
    internalState.update(
        StreamSupport.stream(sp, size > PARALLEL_THRESHOLD)
                     .collect(customCollector()));
}

spliterator()是一个使用输入流的终端操作,但您可以将spliterator传递给StreamSupport.stream以构造具有完全相同属性的流。第二个参数已经告诉流是否应该是并行的。

理论上。

另一个问题是根本性的。元素的数量实际上并不能说明在并行处理中是否会有好处。这取决于每个元素的工作负载,它不仅取决于您的终端collection操作,而且还取决于在进入您的方法之前已经链接到流的操作。即使您认为收集器的工作负载已经足够高,值得并行处理,也可能是传入流具有诸如skiplimitdistinct(在有序流上)之类的操作,这些操作的并行性通常较差,并且需要完全不同的阈值。

更简单的解决方案是让调用方来决定,因为调用方对流的大小和性质有所了解。您甚至不需要在方法的签名中添加一个选项,因为调用方已经可以通过在将流传递给您的方法之前对其调用Parallear()Sequential()来做出决定,您只需不更改模式就可以尊重这一点。

 类似资料:
  • 下面是我想在可能的情况下仅使用流式API复制的非流代码: 当然,对于流来说,简单的迭代很容易: 但我需要添加“before”和“after”行,前提是过滤后流不是空的。这可能在一个语句中实现,还是我需要收集? 这似乎不是一个更好的解决方案。。。

  • 在过去的几天里,测试我情绪的问题是,尽管我的ESP8266芯片完全能够在while循环中通过parsePacket获取数据包,但当我既想监听传入的数据包,又想让我的ESP8266读取传感器并通过wifi发送这些数据包时,它完全忽略了这些。 所以我删掉了所有与传感器有关的内容,并在下面粘贴了代码,但下面是正在发生的事情。 在Setup()中,ESP设置wifi、SoftAP节点、UDP并进行配置 然

  • 其他操作 执行 sudo mn -c 会进行清理配置操作,适合故障后恢复。 执行 exit 会退出 Mininet 的 CLI,同时给出运行时间统计。 py cmd 使用 Python 来执行 cmd。 测试 Mininet 启动后立刻关闭的时间可以用 sudo mn --test none。

  • 示例: 当我在测试套件中执行这些类时,首先执行类1的@test,然后打开一个新的浏览器实例,其中执行类2的@test。现在执行类1的第二个@test,然后执行类2的第二个@test。注意:在这种情况下测试并行为false。需要知道为什么会这样。我希望第一类的执行在第二类开始之前完成。我想不通。我做了一些变通办法,但没有奏效。 提前道谢。

  • 问题内容: 在下面的代码中,我试图一次性进行多个(大约10个)HTTP请求和RSS解析。 我在需要访问和解析结果的URI数组上使用标准构造。 码: 我了解一次调用函数时,应该使用回调。但是,在此示例中,我唯一想到使用回调的方法是调用一个函数,该函数对被调用的次数进行计数,并且仅在被调用的次数与看起来很hacky 的次数相同时才继续。 所以我的问题是, 在node.js中处理这种情况的最佳方法 是

  • 问题内容: 我的页面上有一个表单。该表单包含一个文本框和一个提交按钮。 提交表单后,通过单击按钮或在文本框中按Enter,我要进行查找(在这种情况下,使用Bing Maps对邮政编码进行地理编码),然后像往常一样将表单提交到服务器。 我当前的方法是将提交事件的处理程序添加到一个表单中,然后在完成后调用Submit(),但是我无法使它正常工作,并且无法调试问题: 问题答案: 是你的朋友在这里。在完成