Объединение этих двух Java потоков в один - PullRequest
2 голосов
/ 24 апреля 2020

есть ли возможность объединить два потока в методе в один, так что есть только одна строка оператора return? Метод должен вычислять сумму каждого столбца в заданном двумерном двойном массиве, неважно, какую структуру имеет массив, но в массиве есть хотя бы один элемент, и допускаются ненулевые строки. Большое спасибо.

public static double[] sumUpCols(double[][] x) {
    double[][] a = Stream.of(x).sorted((a0, a1) -> a1.length - a0.length).toArray(double[][]::new);
    return IntStream.range(0, a[0].length).mapToDouble(i -> IntStream.range(0, a.length).mapToDouble(j -> i < a[j].length ? a[j][i] : 0.0).sum()).toArray();
}

public static void main(String[] args) {
    double[][] x = { { 1 }, { 2, 3 }, { 4, 5, 6 }, { 5, 2 } };
    System.out.println(Arrays.toString(sumUpCols(x)));
}

Ответы [ 4 ]

1 голос
/ 24 апреля 2020

пробная проба без сортировки массива путем преобразования его в карту, где индекс столбца является ключом, а значение является суммой столбца:

Collection<Double> values = Arrays.stream(x)
      .flatMap(b -> IntStream.range(0, b.length)
                    .mapToObj(i -> new AbstractMap.SimpleEntry<Integer, Double>(i, b[i])))
      .collect(groupingBy(e -> e.getKey(), summingDouble(v -> v.getValue())))
      .values();
1 голос
/ 24 апреля 2020
public static double[] sumUpCols(double[][] x) {
     // return Stream.of(x).mapToDouble((double[] row) -> DoubleStream.of(row).sum()).toArray();

     return Stream.of(x)
            .sorted((a0, a1) -> a1.length - a0.length)
            .reduce((double[] left, double[] right) -> {
                IntStream.range(0, right.length).forEach(i -> left[i] += right[i]);
                return left;
    }).get();
}
0 голосов
/ 26 апреля 2020

лямбда с уменьшением - без использования map, flatMap или дополнительного IntStream

public static double[] sumUpCols(double[][] x) {
  double[][] sum = new double[][] { {0}, {} };
  return( Stream.of( x ).reduce( (a1, a2) -> {
    for( int i = 0; i < a1.length || i < a2.length; i++ ) {
      sum[0] = Arrays.copyOf( sum[0], i + 1 );
      sum[0][i] = 0;
      try {
        sum[0][i] += a1[i];
      }
      catch( ArrayIndexOutOfBoundsException ex ) {}  // ignored
      try {
        sum[0][i] += a2[i];
      }
      catch( ArrayIndexOutOfBoundsException ex ) {}  // ignored
    }
    return sum[0];
  } ).get() );
}

увеличивает массив результатов динамически
может обрабатывать и пустые строки

получает: [12.0, 10.0, 6.0]

0 голосов
/ 24 апреля 2020

Не совсем обход одного потока, но немного лучше подходить для определения максимально возможной длины для вложенного массива. Затем итерируйте, используя его в качестве индексов и

public static double[] sumUpColumns(double[][] x) {
    return IntStream.range(0, Stream.of(x).mapToInt(a -> a.length).max().orElse(0))
            .mapToDouble(i -> Arrays.stream(x)
                    .mapToDouble(item -> i < item.length ? item[i] : 0.0)
                    .sum())
            .toArray();
}
...