java - 如何使用 Java 8 Streams 以特定方式实现 zip?

标签 java java-8 java-stream

我正在尝试弄清楚如何使用 Streams API 来实现一个 zip 函数,该函数将无限数量的 int[] 作为参数;从每个元素中取出第 i 个元素;将它们放在元组中(显然需要自定义元组对象——我有)并返回元组列表(即列表)。

本质上,对于:

{ 1, 2, 3 }
{ 4, 5, 6 }

提议的方法应该返回: [ Tuple(1, 4), Tuple(2, 5), Tuple(3, 6) ]作为java.util.List<Tuple>

这是一个以“正常”方式执行我正在尝试执行的操作的函数:

/**
 * Return a list of tuples, where each tuple contains the i-th element
 * from each of the argument sequences.  The returned list is
 * truncated in length to the length of the shortest argument sequence.
 *
 * @param args  the array of ints to be wrapped in {@link Tuple}s
 * @return a list of tuples
 */
public static List<Tuple> zip(int[]... args) {
    List<Tuple> retVal = new ArrayList<>();
    // Find the array with the minimum size
    int minLength = Arrays.stream(args).map(i -> new Integer(i.length)).min((a, b) -> a.compareTo(b)).get();

    for(int i = 0;i < minLength;i++) {
        Tuple.Builder builder = Tuple.builder();
        for(int[] ia : args) {
            builder.add(ia[i]);
        }
        retVal.add(builder.build());
    }

    return retVal;
}

最佳答案

一个解决方案是在索引上创建一个 Stream 并使用 mapToObj 将每个 int 映射到一个 Tuple 中。此外,由于您已经有了一个 Builder 对象,我们可以利用它来将元素收集到其中。

假设我们添加一个方法 Tuple.Builder.addAll(Tuple.Builder other) 其目的是将一个构建器添加到另一个构建器,我们可以有以下代码:

public static List<Tuple> zip(int[]... args) {
    // Find the array with the minimum size
    int minLength = Arrays.stream(args).mapToInt(i -> i.length).min().orElse(0);

    return IntStream.range(0, minLength)
                    .mapToObj(i -> 
                       Arrays.stream(args)
                             .mapToInt(ia -> ia[i])
                             .collect(Tuple::builder, Tuple.Builder::add, Tuple.Builder::addAll)
                             .build()
                    ).collect(Collectors.toList());
}

(如果您不想支持并行执行,您可以使用 (b1, b2) -> { throw new IllegalStateException(); } 抛出异常,而不添加 addAll 方法。)


作为旁注,查找最小数组大小的代码可以简化:您不需要装箱到 Integer 中,您只需将每个数组映射到它的长度并得到最小值 min() .这将返回一个 OptionalInt;我使用 orElse(0) 代替获取它的值(如果 Stream 为空则可能会引发异常),这样,在 Stream 为空的情况下,将返回一个空列表。

关于java - 如何使用 Java 8 Streams 以特定方式实现 zip?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34838563/

相关文章:

java - 使用 Try With 资源

java - 通过谓词限制流

Java8 将来自流的随机点与来自其他流的播放器对象相关联

JAVA 8 Stream 过滤器使用 Predicate 获取最新记录

java - 我想将 computeIfPresent 和 putIfAbsent 都放到一个原子函数中

java - 为什么这个 java Stream 被操作了两次?

java - 处理异常和错误(错误是可以的)

java - Spring boot 无法运行,但服务 UTest 运行良好

java - 模式匹配器替换全部

java - AtomicInteger.updateAndGet() 和 AtomicInteger.accumulateAndGet() 之间在功能上有什么区别吗?