在Java中使用流初始化二维数组

3

我有以下的类:

public class MyClass {
    //...
    public MyClass(int x, int y) {
        //...
    }
}

现在,我需要用这些项初始化一个二维数组:

int rows;
int cols;
//initializing rows and cols
MyClass[][] arr = new MyClass[rows][cols];
//how to initialize arr[x][y] with 
//new MyClass(x, y) with streams API

我看了这个例子,但在我的情况下它不起作用:Java 8 Stream and operation on arrays。他们使用单个IntStream

问题:当然,我可以使用嵌套的for循环,但我认为这种方式已经过时并且被认为是不好的。那么如何应用流api并以Java 8的方式初始化呢?

4个回答

5

流不太擅长跟踪索引,而你在这里需要它。所以你可以像@NicolasFilotto建议的那样滥用它们,或者用更简单的方法:

MyClass[][] array = new MyClass[rows][cols];
IntStream.range(0, rows)
        .forEach(r -> IntStream.range(0, cols)
                .forEach(c -> array[r][c] = new MyClass(r, c)));

你甚至可以让它看起来更加实用,摆脱forEach和变异部分:
MyClass[][] array = IntStream.range(0, rows)
        .mapToObj(r -> IntStream.range(0, cols)
                .mapToObj(c -> new MyClass(r, c))
                .toArray(MyClass[]::new))
        .toArray(MyClass[][]::new);

但说实话,for循环并不过时:
for (int r = 0; r < rows; r++) {
    for (int c = 0; c < cols; c++) {
        array[r][c] = new MyClass(r, c);
    }
}

1
你可以使用两个嵌套的 IntStream 生成一个二维数组,如下所示:
public static void main(String[] args) {
    int rows = 2, cols = 3;
    // generate an array
    MyClass[][] arr = IntStream.range(0, rows)
            .mapToObj(x -> IntStream.range(0, cols)
                    .mapToObj(y -> new MyClass(x, y))
                    .toArray(MyClass[]::new))
            .toArray(MyClass[][]::new);
    // output
    Arrays.stream(arr).map(Arrays::toString).forEach(System.out::println);
    //[{x=0, y=0}, {x=0, y=1}, {x=0, y=2}]
    //[{x=1, y=0}, {x=1, y=1}, {x=1, y=2}]
}

public static class MyClass {
    int x, y;

    public MyClass(int x, int y) {
        this.x = x;
        this.y = y;
    }

    @Override
    public String toString() {
        return "{x=" + x + ", y=" + y + "}";
    }
}

1
这是一种方法:

这样做:

int rows = 5;
int cols = 10;
MyClass[][] arr = new MyClass[rows][cols];
Stream.generate(new Supplier<MyClass>() {
    int currentValue = 0;
    @Override
    public MyClass get() {
        MyClass myClass = new MyClass(currentValue / cols, currentValue % cols);
        currentValue++;
        return arr[myClass.x][myClass.y] = myClass;
    }
}).limit(rows * cols).forEach(System.out::println);

输出:

MyClass{x=0, y=0}
MyClass{x=0, y=1}
MyClass{x=0, y=2}
...
MyClass{x=4, y=9}

0

适应解决方案的 Integer[][],参考 answered assylias

package com.gmail.jackkobec.java.core;

import java.util.Arrays;
import java.util.Random;
import java.util.stream.IntStream;

/**
 * @Author Jack <jackkobec>
 */
public class InitMatrixByStreamApi {
    public static final int ROWS_COUNT = 5; // Matrix rows number
    public static final int COLUMN_COUNT = 2; // Matrix columns number

    public static void main(String[] args) {
        Integer[][] matrixFromStreamApi = initMatrixInStream(ROWS_COUNT, COLUMN_COUNT);
        printMatrix(matrixFromStreamApi);
    }

    /**
     * Init matrix by random int values with border 777
     *
     * @param rowsCount    - Matrix rows number
     * @param columnsCount - Matrix columns number
     * @return Integer[][]
     */
    public static Integer[][] initMatrixInStream(int rowsCount, int columnsCount) {
        return IntStream.range(0, rowsCount)
                .mapToObj(rowArray -> IntStream.range(0, columnsCount)
                        .mapToObj(columnArrayElement -> new Random().nextInt(777))
                        .toArray(Integer[]::new))
                .toArray(Integer[][]::new);
    }

    /**
     * Prints matrix.
     *
     * @param matrix
     */
    public static void printMatrix(Integer[][] matrix) {
        Arrays.stream(matrix)
                .map(array -> Arrays.toString(array) + "\n")
                .forEach(System.out::println);
    }
}

输出:

[395, 58]
[361, 652]
[291, 76]
[112, 77]
[186, 282]

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