Java 8 中流的笛卡尔积作为流(仅使用流)

2024-02-11

我想创建一种方法,该方法创建一个元素流,这些元素是多个给定流的笛卡尔积(最后由二元运算符聚合为相同类型)。请注意,参数和结果都是流,not收藏。

例如,对于两个流{A, B} and {X, Y}我希望它产生价值流{AX、AY、BX、BY}(简单的串联用于聚合字符串)。到目前为止,我已经想出了这段代码:

private static <T> Stream<T> cartesian(BinaryOperator<T> aggregator, Stream<T>... streams) {
    Stream<T> result = null;

    for (Stream<T> stream : streams) {
        if (result == null) {
            result = stream;
        } else {
            result = result.flatMap(m -> stream.map(n -> aggregator.apply(m, n)));
        }
    }

    return result;
}

这是我想要的用例:

Stream<String> result = cartesian(
  (a, b) -> a + b, 
  Stream.of("A", "B"), 
  Stream.of("X", "Y")
);

System.out.println(result.collect(Collectors.toList()));

预期结果:AX, AY, BX, BY.

另一个例子:

Stream<String> result = cartesian(
  (a, b) -> a + b, 
  Stream.of("A", "B"), 
  Stream.of("K", "L"), 
  Stream.of("X", "Y")
);

预期结果:AKX, AKY, ALX, ALY, BKX, BKY, BLX, BLY.

但是,如果我运行代码,我会收到以下错误:

IllegalStateException:流已被操作或关闭

流消耗在哪里?经过flatMap?可以轻松修复吗?


在您的示例中传递流永远不会比传递列表更好:

private static <T> Stream<T> cartesian(BinaryOperator<T> aggregator, List<T>... lists) {
    ...
}

并像这样使用它:

Stream<String> result = cartesian(
  (a, b) -> a + b, 
  Arrays.asList("A", "B"), 
  Arrays.asList("K", "L"), 
  Arrays.asList("X", "Y")
);

在这两种情况下,您都从可变参数创建一个隐式数组并将其用作数据源,因此惰性是虚构的。您的数据实际上存储在数组中。

在大多数情况下,生成的笛卡尔积流比输入长得多,因此实际上没有理由让输入变得懒惰。例如,有五个包含 5 个元素的列表(总共 25 个),您将得到包含 3125 个元素的结果流。所以在内存中存储25个元素并不是什么大问题。实际上在大多数实际情况下它们已经存储在内存中。

为了生成笛卡尔积流,您需要不断“倒带”所有流(第一个流除外)。要倒带,流应该能够一次又一次地检索原始数据,要么以某种方式缓冲它们(您不喜欢),要么再次从源(集合、数组、文件、网络、随机数等)中获取它们。 )并一次又一次地执行所有中间操作。如果您的源操作和中间操作很慢,那么惰性解决方案可能比缓冲解决方案慢得多。如果您的源无法再次生成数据(例如,随机数生成器无法生成之前生成的相同数字),则您的解决方案将是错误的。

尽管如此,完全懒惰的解决方案是可能的。不使用流,而是使用流供应商:

private static <T> Stream<T> cartesian(BinaryOperator<T> aggregator,
                                       Supplier<Stream<T>>... streams) {
    return Arrays.stream(streams)
        .reduce((s1, s2) -> 
            () -> s1.get().flatMap(t1 -> s2.get().map(t2 -> aggregator.apply(t1, t2))))
        .orElse(Stream::empty).get();
}

该解决方案很有趣,因为我们创建并减少供应商流以获得最终的供应商并最终调用它。用法:

Stream<String> result = cartesian(
          (a, b) -> a + b, 
          () -> Stream.of("A", "B"), 
          () -> Stream.of("K", "L"), 
          () -> Stream.of("X", "Y")
        );
result.forEach(System.out::println);
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Java 8 中流的笛卡尔积作为流(仅使用流) 的相关文章

随机推荐

  • 我们如何访问堆栈变量而不弹出它们?

    据我所知 C 中有两种变量 栈变量和堆变量 堆栈变量速度很快 并由编译器和 CPU 自动管理 我关于堆栈变量的问题是 堆栈变量真的存储在堆栈 FILO 数据结构中吗 如果是这样 为什么我们可以使用它们而不弹出它们并丢失它们的值 为什么要用栈
  • DidSelectRow 方法由于 tapGestureRecognizer 而被禁用

    我正在 swift 3 0 中开发一个项目 我有 UIViewController 来填充一些文本字段 因此 我使用表视图作为下拉菜单 一旦选择一行 它将被分配给 UILabel 此外 我还添加了 UITapGuestureRecogniz
  • 获取数组中第一个条目的指针

    我想获取数组中第一个条目的指针 这就是我尝试的方法 int Results 1 2 3 4 5 unsafe int FirstResult Results 0 得到以下编译错误 有什么想法如何修复它吗 您只能获取 a 中不固定表达式的地址
  • DebugBreak 不中断

    我正在用 C 编写一个类 但无法使用 F5 进行调试 该代码将从另一个调用它的 服务 运行 过去我用过 debugbreak 当我看到一个窗口告诉我抛出异常时 选择对其进行调试 最近我更新到了Windows 7 它一直工作了一段时间 今天
  • Android 8.0 中的 HTTP Volley 标头

    自从 Android 8 0 发布以来 我遇到了授权标头的问题 还有其他方法可以将标头添加到 Volley 请求中吗 这在最新的 Android 版本上无法正常工作 override public Map
  • 嘲笑日延长

    在我需要测试的代码中我使用 import dayjs from dayjs import utc from dayjs plugin utc dayjs extend utc dayjs add 15 minute 在我的测试中 我需要模拟
  • 从另一个线程在主线程上运行方法

    我的模型类必须从互联网获取一些数据 所以我决定在另一个线程上运行它 这样用户界面就不会冻结 因此 当一个对象需要一些数据时 它首先使用这种类型的方法询问模型 void giveMeSomeData id object withLabel i
  • Spring Security:在 servlet Filter 内访问当前经过身份验证的用户

    我最近开始学习 Spring Security 今天我解决了这个基本的 我相信 问题 为什么我不能访问 Servlet Filter 内的当前主体 如下面的类所示 package com acme test import java io I
  • 错误:stdClass 类的对象无法转换为字符串

    当我运行下面的代码时 id Input get branch id retailer code DB table branches gt select retailer code gt where id id gt first user n
  • Azure 上的 Web Api 使用“return InternalServerError(ex)”不显示错误详细信息

    我的 Web Api 在本地运行时 在发布模式下 将返回以下格式的任何错误 Message An error has occurred ExceptionMessage No text specified ExceptionType Sys
  • 如何在 PrimeFaces 中的 CommandButton 上定义带有闭包的 oncomplete 事件?

    我正在使用一些 JavaScript 交互性扩展 PrimeFaces 应用程序的一部分 一切都始于CommandButton它从 bean 获取一些数据并调用 JavaScript 目前 它看起来像这样
  • 如何显示xml文件中的视频?

    您好 我使用下面给出的 xml 文件 如何从 xml 文件获取视频
  • 使用CMD在Mysql中导入压缩文件

    我正在尝试使用命令提示符将压缩数据库文件导入 Mysql 使用以下命令 7z lt backup sql 7z mysql u root test The root user don t有什么password与之相关 test是我的目标空白
  • WinForm应用程序数据持久化(C#)

    我相信 ASP NET 应用程序中 可变短期 持久性的最佳方法是 会话变量 会话范围 应用变量 应用范围 页面视图 页面范围 应用设置 应用范围 Windows 窗体应用程序中 可变短期 持久性的最佳方法是什么 表格范围 用户会话范围 应用
  • 如何将数据转换为非等列?

    我有一个事件数据集 按以下分组let像这样 set seed 3 events lt data frame let rep LETTERS 1 2 each 3 age c 0 sample 1 20 size 2 0 sample 1 2
  • 使用 boost 的 async_write 的异步 tcp 服务器会导致错误的文件描述符

    首先 我不是以英语为母语的人 所以我可能会犯一些语法错误 对此感到抱歉 我正在尝试使用 C 和 Boost 创建一个异步 TCP 服务器 我已经成功接受客户并收到他们的消息 但我无法回复他们的消息 我想要实现的是在 TCPServer 类上
  • 从 Xamarin / C# 中的 URL 加载 UIImage

    已经过去4年了这个问题 https stackoverflow com questions 2095635 load an image from a url已得到答复这篇博文 http escoz com blog displaying w
  • 使用 PHP 从 Microsoft Teams 自定义机器人验证 HMAC

    我正在尝试使用 PHP 验证 Microsoft Teams 自定义机器人 遵循 Microsoft指示 https learn microsoft com en us microsoftteams platform concepts cu
  • CUDA 确定每个块的线程、每个网格的块

    我是 CUDA 范式的新手 我的问题是确定每个块的线程数和每个网格的块数 这是否需要一些艺术和尝试 我发现许多例子似乎为这些事情选择了任意的数字 我正在考虑一个问题 我可以将任意大小的矩阵传递给乘法方法 这样 C 的每个元素 如 C A B
  • Java 8 中流的笛卡尔积作为流(仅使用流)

    我想创建一种方法 该方法创建一个元素流 这些元素是多个给定流的笛卡尔积 最后由二元运算符聚合为相同类型 请注意 参数和结果都是流 not收藏 例如 对于两个流 A B and X Y 我希望它产生价值流 AX AY BX BY 简单的串联用