Before Java 8 versions, we can initialize a two-dimensional array using for loop like below. How can I do the below in JDK 1.8 using lambda expressions?
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
. This will create a continuous stream of integers from 0
inclusive to n
exclusive. So for a 3 x 3 matrix, the IntStream
is 0, 1, 2
. make another IntStream
for each integer in the outer stream from 0
to number of columns - also 3.
You cannot increment v
in a stream because it must be "effectively final". 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).
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. 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.
Remember, simplicity is key.
I highly recommend you stick with using the for-loop
for initialization of arrays with primitive values. 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. its method IntStream::toArray
reutrns int[]
.
The composition of the outer array is a bit tricky since int[]
is no longer a primitive value but an array itself. 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[][]
.
The parameter passed is simple. int[][]::new
is nothing different than i -> new int[a][b]
.
You can use a combination of the IntStream
methods range
and 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. Using toArray
removes the need to create and modify the array yourself and would enable parallel processing.
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.
Here is a stream solution that is "nested for cycles" look a like.
Output for int[][] board = new int[4][2];
[[1, 6], [2, 7], [3, 8], [4, 9]]
Output for int[][] board = new int[4][3];
[[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
)
);
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.