I'm wondering if there is a more condensed way of doing the following in Java 8 with streams:
public static double[] multiply(double[][] matrix, double[] vector) {
int rows = matrix.length;
int columns = matrix[0].length;
double[] result = new double[rows];
for (int row = 0; row < rows; row++) {
double sum = 0;
for (int column = 0; column < columns; column++) {
sum += matrix[row][column]
* vector[column];
}
result[row] = sum;
}
return result;
}
Making an Edit. I received a very good answer, however the performance is about 10X slower than the old implementation, so I'm adding the test code here in case anyone wants to investigate it:
@Test
public void profile() {
long start;
long stop;
int tenmillion = 10000000;
double[] vector = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
double[][] matrix = new double[tenmillion][10];
for (int i = 0; i < tenmillion; i++) {
matrix[i] = vector.clone();
}
start = System.currentTimeMillis();
multiply(matrix, vector);
stop = System.currentTimeMillis();
}
A direct way using Stream would be the following:
public static double[] multiply(double[][] matrix, double[] vector) {
return Arrays.stream(matrix)
.mapToDouble(row -> IntStream.range(0, row.length)
.mapToDouble(col -> row[col] * vector[col])
.sum())
.toArray();
}
This creates a Stream of each row of the matrix (Stream<double[]>
), then maps each row to the double value resulting of calculating the product with the vector
array.
We have to use a Stream over the indexes to calculate the product because there are unfortunately no built-in facility to zip two Streams together.