在Java中从二维数组流式处理数据

40

我正在尝试从一个n维的int数组中获取一个IntStream。是否有一种不错的API方法可以实现呢? 我知道如何将两个流连接起来。


2
您能否提供更多关于数据的细节以及您希望如何交付数据的信息? - Ale Zalazar
我只有一个二维整数数组。我认为解决方案不依赖于数据? - SurenNihalani
您希望IntStream遍历int[][]中的每个int吗? - Sotirios Delimanolis
Java 8 中的 Arrays 类有一个公共的静态<T> Stream<T> stream(T[] array) 方法。我想这应该可以解决问题。但是我认为 IntStream 只适用于 n=1。 - Ale Zalazar
4个回答

55

假设您要按行顺序依次处理二维数组,以下代码应该可行:

int[][] arr = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream stream = Arrays.stream(arr).flatMapToInt(x -> Arrays.stream(x));

首先,它调用Arrays.stream(T[])方法,其中T被推断为int[],以获取一个Stream<int[]>,然后Stream#flatMapToInt()方法使用Arrays.stream(int[])方法将每个int[]元素映射到一个IntStream


@SotiriosDelimanolis,所以它确实会给出一个遍历数组的IntStream,就像1、2、3、4、5、6、... - Rohit Jain
1
是的。传递给flatMapToIntFunction获取int [][]中的每个元素,即单个int [],并构造并返回一个新的IntStream。将所有这些连接成一个最终的IntStream并返回。(不完全准确,但您可以这样考虑。) - Sotirios Delimanolis
这个整个的“函数式”东西对我来说是新的 :| - Sotirios Delimanolis

18

进一步扩展Rohit的答案,方法引用可以用来略微缩短所需代码的数量:

int[][] arr = { {1, 2, 3}, 
                {4, 5, 6},
                {7, 8, 9} };

IntStream stream = Arrays.stream(arr).flatMapToInt(Arrays::stream);

2

如果只处理元素,请使用flatMap,就像Rohit的答案一样。

如果要处理带有索引的元素,则可以使用IntStream.range,如下所示。

import java.util.stream.IntStream;
import static java.util.stream.IntStream.range;

public class StackOverflowTest {
    public static void main(String... args) {
        int[][] arr = { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } };
        // Map the two dimensional array with indices.
        final IntStream intStream = range(0, arr.length).flatMap(row -> range(0, arr[row].length).map(col -> {
            final int element = arr[row][col];
            // E.g. multiply elements in odd numbered rows and columns by two.
            return row % 2 == 1 || col % 2 == 1 ? element * 2 : element;
        }));
        // Prints "1 4 3 8 10 12 7 16 9 ".
        intStream.forEachOrdered(n -> System.out.print(n + " "));
    }
}

2
除了之前的回答,方法Arrays::stream返回一个顺序流(请参见:Oracle Javadoc)。在某些情况下,使用并行流可以提高性能。要显式请求并行流,您需要先通过Arrays::asList将其转换为列表,然后在结果列表上调用parallelStream()
要使用IntStream计算二维int数组的总和,您可以使用以下代码:
int[][] twoDimArray = { {1, 2, 3}, {4, 5, 6}, {7, 8, 9} };
IntStream intStream = Arrays.asList(twoDimArray)
    .parallelStream()               // "rows" in parallel
    .flatMapToInt(Arrays::stream);  // "columns" sequentially
int sum = intStream.sum();          // = 45

为处理外层(行,第一维)创建的流现在正在并行执行,而内层(列,第二维)的流仍然是顺序的(使用上述提到的Arrays::stream)。

根据数组的大小和结构,您可能会看到4倍的性能提升(这是我在自己的测试中测量到的),也可能没有任何提升。如果您的计算时间很关键,那么使用并行流值得一试。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接