在单遍中执行多次还原

2024-04-03

在流的单次传递中执行多次归约的习惯用法是什么?是否只是拥有一个大的减速器类,即使这违反了 SRP(如果需要不止一种类型的减速计算)?


大概您希望避免进行多次传递,因为管道阶段可能很昂贵。或者您希望避免收集中间值以便通过多个收集器运行它们,因为存储所有值的成本可能太高。

As 布莱恩·戈茨指出 https://stackoverflow.com/questions/29181682/performing-more-than-one-reduction-in-a-single-pass#comment46586618_29181682, Collectors.summarizingInt将收集int值并对它们执行多次归约,返回一个称为的聚合结构IntSummaryStatistics。有类似的收藏家进行总结double and long values.

不幸的是,它们只执行一组固定的缩减,因此如果您想要执行与它们不同的缩减,则必须编写自己的收集器。

这是一种在单次传递中使用多个不相关的收集器的技术。我们可以用peek()破解流中的每个值,使其不受干扰地通过。这peek()操作需要一个Consumer,所以我们需要一种方法来适应Collector to a Consumer. The Consumer将成为收藏家的累加器功能。但我们还需要致电收藏家supplier函数并存储它创建的对象以传递给累加器功能。我们需要一种方法从收集器中获取结果。为此,我们将收集器包装在一个小帮助器类中:

public class PeekingCollector<T,A,R> {
    final Collector<T,A,R> collector;
    final A acc;

    public PeekingCollector(Collector<T,A,R> collector) {
        this.collector = collector;
        this.acc = collector.supplier().get();
    }

    public Consumer<T> peek() {
        if (collector.characteristics().contains(Collector.Characteristics.CONCURRENT))
            return t -> collector.accumulator().accept(acc, t);
        else
            return t -> {
                synchronized (this) {
                    collector.accumulator().accept(acc, t);
                }
            };
    }

    public synchronized R get() {
        return collector.finisher().apply(acc);
    }
}

要使用它,我们首先必须创建包装的收集器并挂载它。然后我们运行管道并调用peek,传递包裹的收集器。最后我们打电话get在包装的收集器上以获得其结果。这是一个简单的示例,它对一些单词进行过滤和排序,同时按首字母对它们进行分组:

    List<String> input = Arrays.asList(
        "aardvark", "crocodile", "antelope",
        "buffalo", "bustard", "cockatoo",
        "capybara", "bison", "alligator");

    PeekingCollector<String,?,Map<String,List<String>>> grouper =
        new PeekingCollector<>(groupingBy(s -> s.substring(0, 1)));

    List<String> output = input.stream()
                               .filter(s -> s.length() > 5)
                               .peek(grouper.peek())
                               .sorted()
                               .collect(toList());

    Map<String,List<String>> groups = grouper.get();
    System.out.println(output);
    System.out.println(groups);

输出是:

[aardvark, alligator, antelope, buffalo, bustard, capybara, cockatoo, crocodile]
{a=[aardvark, antelope, alligator], b=[buffalo, bustard], c=[crocodile, cockatoo, capybara]}

这有点麻烦,因为您必须为包装的收集器写出泛型类型(这有点不寻常;它们通常都是推断出来的)。但如果处理或存储流值的费用足够大,也许值得这么麻烦。

最后请注意peek()如果流并行运行,则可以从多个线程调用。因此,非线程安全收集器必须受到保护synchronized堵塞。如果收集器是线程安全的,我们不需要在调用它时进行同步。为了确定这一点,我们检查收集器的CONCURRENT特征。如果您运行并行流,最好放置一个并发收集器(例如groupingByConcurrent or toConcurrentMap)内peek操作,否则包装收集器内的同步可能会导致瓶颈并减慢整个流的速度。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

在单遍中执行多次还原 的相关文章

随机推荐

  • 编译器如何为 C++ 中条件声明的自动变量分配内存?

    假设我有一个函数 根据某些运行时条件创建昂贵的自动对象或创建便宜的自动对象 void foo if runtimeCondition int x 0 else SuperLargeObject y 当编译器为此函数分配堆栈帧的内存时 它是否
  • jquery selectedIndex 不起作用

    我有一个带有许多选择标签的 from 当用户提交表单时 我想检查用户是否为所有选择标签选择一个选项 这是我的 jquery 代码 apForm select each function var this this if this selec
  • Kubernetes 配置映射符号链接 (..data/):有办法避免它们吗?

    我注意到 当我创建并安装包含一些文本文件的配置映射时 容器会将这些文件视为符号链接 data myfile txt 例如 如果我的配置映射名为 tc configs 并包含 2 个名为 stripe1 xml 和 stripe2 xml 的
  • CSS Calc((100%/5)+10px) 不起作用

    好吧 在我的 CSS 中 我正在尝试进行数学计算 calc 100 5 10px 当我这样做时 它不起作用 当我计算时 100 5 它工作得很好 我需要做什么才能让 10px 正常工作 您需要做的是使用正确的语法 calc 100 5 10
  • 如何在 Ionic 框架中使用 CSS 选择器隔离特定平台

    我遇到了一种罕见的情况 尽管考虑到 Android 和 iOS 之间的行为不同 这是可以理解的 我想在我正在 Ionic 框架上开发的 Cordova 应用程序中使用专门针对 iOS 的不同样式 我想知道基于平台隔离选择器的最佳方法 基本上
  • 如何通过azure云服务上的kubernetes检查持久卷的内容

    我已将软件打包到容器中 我需要通过Azure容器服务将容器放入集群 该软件具有目录的输出 src data 我想访问整个目录的内容 搜索后 我必须解决 在azure上使用Blob存储 但是搜索后 我找不到可执行方法 使用持久卷 但是我找到的
  • Python Pygame 游戏灯光

    我正在制作一款 2D 横向卷轴游戏 游戏中的一个物品是火炬 我有一个手臂可以旋转的玩家 我们可以获取手臂的角度 我正在寻找跟随手臂角度的三角形光束形状 我有一些想法 比如在整个屏幕上放置一个 alpha 图像 并根据手臂角度单独从每个像素中
  • 具有扩展方法的 Kotlin 数据绑定

    我正在尝试在 Android 的数据绑定中使用 Kotlin 扩展方法 例如 调用 onclick 处理程序 所以我编写了这段代码 posttest list item xml
  • 输入文件大小和内容在 macOS 上不会更新

    我编写了一个基于网络的小型工具 它使用文件输入来读取不断变化的文件 用户手动选择它 一次 JavaScript 会跟踪它的更改时间 上次文件修改时间和文件大小 如果已更改 则会再次读取文件内容 这在 Windows 上的所有浏览器中都可以正
  • PHP AWS SDK 3错误:AWS HTTP错误:cURL错误6:无法解析主机:s3.oregon.amazonaws.com

    我正在尝试连接到 AWS 版本 3 SDK 存储桶 但是 我收到以下错误 PHP 致命错误 未捕获异常 Aws S3 Exception S3Exception 并显示消息 在 上执行 PutObject 时出错 https s3 oreg
  • 我如何在 codeigniter 中创建一个虚荣网址

    我如何在 codeigniter 中创建一个虚荣网址 我在框架中执行此操作确实遇到困难 而且似乎没有任何好的答案 有可能 我正在我的一个项目中使用它 这是 CodeIgniter 论坛上的一个帖子 展示了如何做到这一点 http codei
  • 您遇到过的最好的源代码注释是什么? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 使用 .NET Core 时是否需要 AssemblyInfo?

    之前 AssemblyInfo cs文件是由 Visual Studio 自动创建的 用于包含程序集范围的属性 如 AssemblyVersion AssemblyName 等 在 NET Core 和 ASP NET Core 中 pro
  • T-SQL - 按周进行透视

    我目前正在尝试创建一个 T SQL 它运行表中的交货列表 并按客户和仓库对它们进行分组 因此每一行都将是 客户 仓库 总价值 称为费率的列的总和 然而 客户希望将 总价值 分为过去 9 周 因此 我们将拥有如下列 而不是总价值 22 01
  • 为什么我的 rustup rust-toolchain 文件没有覆盖默认值?

    我想使用 Rust 每晚 构建来与 Arrow 和 Datafusion 配合使用 根据这个帖子 https stackoverflow com questions 58226545 how to switch between rust t
  • ESP8266 I2C从机不确认数据

    我有一个 TM4C123 处理器作为 I2C 主处理器 一个 ESP8266 作为从处理器 对于 ESP 我使用的是 Arduino IDE 并在 2 5 2 版安装了 ESP8266 支持 它应该支持 I2C 从模式 但是 我无法让它工作
  • NsdManager.DiscoveryListener.onServiceFound 的 NsdServiceInfo 中 Host 为 null

    我试图将 NsdServiceInfo 的 mHost 作为参数传递给 NsdManager DiscoveryListener onServiceFound 但它为空 我有两个 Android 设备 其中设备 1 是服务器 设备 2 是客
  • 如何添加到表过滤器以允许多个复选框选择以及从下拉列表中进行过滤?

    我有一个可以通过多个复选框以及 选择 下拉列表进行过滤的表格 本质上 我想要做的是单击多个复选框 以便找到包含该类 例如类 1 和 3 的每一行 然后按位置对其进行过滤 此时我已经非常接近了 我可以从复选框中选择位置 这也是一个类 两个字母
  • 基于正则表达式以闪亮方式突出显示 DT 中的单词

    使用闪亮的 DT 我希望能够突出显示所选单词 环境searchHighlight TRUE接近我想要的 但这也会突出显示包含搜索的单词 例如 如果我搜索 on 它也会匹配 stone 突出显示中间的 on 示例图片 我可以优化搜索选项reg
  • 在单遍中执行多次还原

    在流的单次传递中执行多次归约的习惯用法是什么 是否只是拥有一个大的减速器类 即使这违反了 SRP 如果需要不止一种类型的减速计算 大概您希望避免进行多次传递 因为管道阶段可能很昂贵 或者您希望避免收集中间值以便通过多个收集器运行它们 因为存