简体   繁体   English

如何在Java 8中初始化二维数组

[英]How to initialize two dimensional array in java 8

Before Java 8 versions, we can initialize a two-dimensional array using for loop like below. 在Java 8版本之前,我们可以使用如下所示的for循环初始化二维数组。 How can I do the below in JDK 1.8 using lambda expressions? 如何在JDK 1.8中使用Lambda表达式执行以下操作?

int[][] board = new int[3][3];
int v = 1;
for (int i = 0; i < board.length; i++) {

    for (int j = 0; j < 3; j++) {

        board[i][j] = v;
        v++;
        System.out.println(v);
    }
}
System.out.println(Arrays.deepToString(board));

Basically, I am looking for an array like below 基本上,我正在寻找像下面的数组

[[1,6],[2,7],[3,8],[4,9]]

Use IntStream . 使用IntStream This will create a continuous stream of integers from 0 inclusive to n exclusive. 这将创建一个连续的整数流,范围从00n不含)。 So for a 3 x 3 matrix, the IntStream is 0, 1, 2 . 因此,对于3 x 3矩阵, IntStream0, 1, 2 make another IntStream for each integer in the outer stream from 0 to number of columns - also 3. 为外部流中从0到列数的每个整数创建另一个IntStream也为3。

You cannot increment v in a stream because it must be "effectively final". 您不能在流中递增v ,因为它必须是“有效最终值”。 Instead we use the equation board[j][i] = 1 + (j + m * i) which is effectively the similar to computing the index of the value if you were to flatten board into a single array (1D matrix). 取而代之的是,我们使用方程board[j][i] = 1 + (j + m * i) ,这实际上与将板展平为单个数组(一维矩阵)时计算值的索引相似。

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

class J {

  public static void main(String[] args) {

    int n = 4;
    int m = 2;

    // n x m matrix
    int[][] board = new int[n][m];

    // Cols (m)
    IntStream.range(0, m).forEach( i -> {

      // Rows (n)
      IntStream.range(0, n).forEach( j -> {

        // Multiply i by row count
        // to account for the row we are in
        board[j][i] = 1 + (j + n * i);
      });


    });

    System.out.println(Arrays.deepToString(board));

  }

}

Output: 输出:

[[1, 5], [2, 6], [3, 7], [4, 8]]

Note: Just because streams allow you to write a neater, functional programming-like syntax, there is often times an associated performance toll. 注意:仅仅因为流允许您编写更整洁的,类似于函数式编程的语法,所以常常会有相关的性能损失。 It stresses the idea, "why fix what's not broken?". 它强调了一个想法:“为什么要修复未损坏的东西?”。 For a 3 x 3 board, you probably won't see a difference. 对于3 x 3的面板,您可能看不到任何区别。 But, if your board were a lot larger, it probably won't prove itself to be worth it, considering all the objects created and extra space used behind the scene. 但是,如果您的木板更大,考虑到所有创建的对象以及幕后使用的额外空间,它可能不会证明自己值得。 Sometimes a simple for-loop (especially when working with arrays) is better. 有时,简单的for循环(尤其是在使用数组时)会更好。

Remember, simplicity is key. 记住,简单是关键。

I highly recommend you stick with using the for-loop for initialization of arrays with primitive values. 我强烈建议您坚持使用for-loop对具有原始值的数组进行初始化。 My recommendation is stronger in the case of a multidimensional array. 对于多维数组,我的建议更强。

However, here is the way: 但是,方法如下:

int a = 4;               // Number of outer array elements
int b = 2;               // Number of inner array elements

int[][] board = IntStream
    .range(0, a)                                               // iterate 0..3
    .mapToObj(i -> IntStream.range(0, b)                       // for each iteratoe 0..1
                            .map(j -> 1 + (i + (a + 1) * j))   // calculate the value
                            .toArray())                        // compose the inner array
    .toArray(int[][]::new);                                    // compose the outer array

Note that the IntStream is able to create an array of primitives since it is a sequence of primitive int-valued elements. 请注意,由于IntStream是原始整数值元素的序列,因此它能够创建原始数组。 its method IntStream::toArray reutrns int[] . 其方法IntStream::toArray返回int[]

The composition of the outer array is a bit tricky since int[] is no longer a primitive value but an array itself. 外部数组的组成有些棘手,因为int[]不再是原始值,而是数组本身。 There is needed to use a method IntStream::mapToObj which maps int to an object - then the Stream<int[]> is returned and the method Stream::toArray(IntFunction<A[]> generator) converting to array with parameter has to be used since you cannot convert Object[] to int[][] . 有需要使用的方法IntStream::mapToObj它映射int的一个对象-然后将Stream<int[]>被返回并且该方法Stream::toArray(IntFunction<A[]> generator)转换为阵列参数有因为无法将Object[]转换为int[][]

The parameter passed is simple. 传递的参数很简单。 int[][]::new is nothing different than i -> new int[a][b] . int[][]::newi -> new int[a][b]没有什么不同。

You can use a combination of the IntStream methods range and iterate : 您可以结合使用IntStream方法rangeiterate

int width = 4, height = 2;

IntStream.rangeClosed(1, width)
         .mapToObj(column -> IntStream.iterate(column, v -> v + width)
                                      .limit(height)
                                      .toArray())
         .toArray(int[][]::new);

By using iterate for the inner loop and rangeClosed(1, width) instead of range(0, width) we can simplify the calcuation a bit. 通过将iterate用于内部循环和rangeClosed(1, width)而不是range(0, width)我们可以稍微简化计算过程。 Using toArray removes the need to create and modify the array yourself and would enable parallel processing. 使用toArray消除了自己创建和修改数组的需要,并且将启用并行处理。

It is important to actually use streams properly to make them more than just weird looking for loops. 重要的是,实际上实际使用流可以使它们不仅仅是寻找怪异的循环。 Merely replacing your loop by a range(0, x).forEach(...) to modify a local variable does not really "use streams", and it is better to stick to for loops then. range(0, x).forEach(...)替换循环以修改局部变量并不能真正“使用流”,因此最好坚持使用for循环。

Here is a stream solution that is "nested for cycles" look a like. 这是“嵌套循环”的流解决方案。

  1. Get the sequence of the numbers from 0 to N(Upper limit exclusive -> N = board.length; 获取从0到N的数字序列(上限不包括-> N = board.length;
  2. Get the sequence of the numbers from 0 to M(Upper limit exclusive -> M = board[i].length; 获取从0到M的数字序列(上限不包括-> M = board [i] .length;
  3. For each of the couples (i, j) set the value of board[i][j] using the func (i + j * step + 1) where step is defined as 5. 对于每对夫妇(i,j),使用func(i + j * step + 1)设置board [i] [j]的值,其中step定义为5。

Output for int[][] board = new int[4][2]; int [] []板的输出= new int [4] [2];

[[1, 6], [2, 7], [3, 8], [4, 9]] [[1,6],[2,7],[3,8],[4,9]]

Output for int[][] board = new int[4][3]; int [] []板的输出= new int [4] [3];

[[1, 6, 11], [2, 7, 12], [3, 8, 13], [4, 9, 14]] [[1、6、11],[2、7、12],[3、8、13],[4、9、14]

int step = 5;

IntStream.range(0, board.length).forEach(i ->
    IntStream.range(0, board[i].length).forEach(j ->
        board[i][j] = i + j * step + 1
    )
);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM