使用流的BlockRealMatrix对象的平均对应行

时间:2018-07-21 21:01:55

标签: java java-stream

我有一个ArrayList <BlockRealMatrix>,每个成员都具有相同的形状,并且想要将每个成员的对应行平均到n行和1列的另一个BlockRealMatrix中,其中n ==#行的任何BlockRealMatrix成员在原始ArrayList中。 从3个循环开始,我设法通过使用流对每个矩阵的行求和来删除一个循环,但是我想尝试摆脱所有循环,并尽可能使用流。谢谢

import org.apache.commons.math3.linear.BlockRealMatrix;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class StreamAdder {

    public static void main(String[] args) {

        List<BlockRealMatrix> matrixHolder = new ArrayList<>();

        matrixHolder.add(new BlockRealMatrix(2, 3));
        matrixHolder.add(new BlockRealMatrix(2, 3));

        matrixHolder.get(0).setRow(0, new double[]{1, 2, 3});
        matrixHolder.get(0).setRow(1, new double[]{4, 5, 6});
        matrixHolder.get(1).setRow(0, new double[]{7, 8, 9});
        matrixHolder.get(1).setRow(1, new double[]{10, 11, 12});

        matrixHolder.stream().forEach(i -> System.out.println(i));

        BlockRealMatrix averages = new BlockRealMatrix(matrixHolder.get(0).getRowDimension(), 1);

        for (int i = 0; i < averages.getRowDimension(); i++) {
            double average = 0;
            for (int j = 0; j < matrixHolder.size(); j++) {
                average += Arrays.stream(matrixHolder.get(j).getRow(i)).sum();
            }
            average /= (matrixHolder.size() * matrixHolder.get(0).getColumnDimension());
            averages.setEntry(i, 0, average);
            average = 0;
        }

        System.out.println("Averages \n" + averages);

    }
}

打印:

BlockRealMatrix{{1.0,2.0,3.0},{4.0,5.0,6.0}}
BlockRealMatrix{{7.0,8.0,9.0},{10.0,11.0,12.0}}
Averages
BlockRealMatrix{{5.0},{8.0}}

1 个答案:

答案 0 :(得分:0)

首先,可以通过直接调用matrixHolder.stream().forEach(i -> System.out.println(i));列表即forEach上的matrixHolder方法或使用方法引用matrixHolder.forEach(i -> System.out.println(i));来进一步改善matrixHolder.forEach(System.out::println);。 / p>

对于更改 all for循环使用流API进行内部迭代。简而言之,这不是一个好问题,因为它会说“在这里使用流会很好”,因此,与其尝试使用流API来更改所有的for循环,不如尝试将其做一点更具可读性:

for (int j = 0; j < matrixHolder.size(); j++) { ... }可以更改为增强的for循环,以使其更具可读性。

for (int i = 0; i < averages.getRowDimension(); i++) {
     double average = 0;
     for (BlockRealMatrix aMatrixHolder : matrixHolder)
           average += Arrays.stream(aMatrixHolder.getRow(i)).sum();
     average /= (matrixHolder.size() * matrixHolder.get(0).getColumnDimension());
     averages.setEntry(i, 0, average);
}

但是,如果您坚持要完全使用流API,那么您可以这样做:

IntStream.range(0, averages.getRowDimension())
         .forEach(i -> {
             double average = matrixHolder.stream()
                                          .mapToDouble(m -> Arrays.stream(m.getRow(i)).sum())
                                          .sum();
             average /= (matrixHolder.size() * matrixHolder.get(0).getColumnDimension());
             averages.setEntry(i, 0, average);
         });