[英]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. 这将创建一个连续的整数流,范围从
0
含0
到n
不含)。 So for a 3 x 3 matrix, the IntStream
is 0, 1, 2
. 因此,对于3 x 3矩阵,
IntStream
为0, 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[][]::new
与i -> new int[a][b]
没有什么不同。
You can use a combination of the IntStream
methods range
and iterate
: 您可以结合使用
IntStream
方法range
和iterate
:
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. 这是“嵌套循环”的流解决方案。
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.