数组

时间:2017-07-03 07:44:42

标签: java arrays java-stream

我对以下情况有疑问;

我在n-number中有ArrayList个数组。数组的数量不是预先确定的,而数组的大小是固定的,但它可以包含空元素,空值被认为是零。我需要将每个单元格的总和放入新数组中的相应索引中,其大小在逻辑上与其他数组相同。

我试图将场景描述如下;

enter image description here

我有一个经典的迭代方法的解决方案,但我最终得到了一个非常脏的实现。我很乐意看到您解决此问题的方法(最好使用Stream api

3 个答案:

答案 0 :(得分:28)

非流解决方案(因为我不认为在流中可以使用易于理解的解决方案):

int[] result = new int[n];  // n is the length of each array.
for (Integer[] array : arrays) {
  for (int i = 0; i < n; ++i) {
    // Increment the i-th element of the result by the i-th element of array.
    // Use 0 in place of null.
    result[i] += array[i] != null ? array[i].intValue() : 0;
    // or (suggested by shmosel)
    // if (array[i] != null) result[i] += array[i];
  }
}

答案 1 :(得分:14)

这是一种方法,灵感来自shmosel's answer

Integer[] result = new Integer[FIXED_SIZE];
Arrays.setAll(result, i -> list.stream().mapToInt(a -> a[i] == null ? 0 : a[i]).sum());

另一种方法是使用自定义收集器:

static <T> Collector<T[], ?, T[]> reducingByColumn(
        T identity,
        BinaryOperator<T> operator,
        IntFunction<T[]> factory) {

    return Collector.of(
        HashMap<Integer, T>::new,
        (map, a) -> IntStream.range(0, a.length)
            .forEach(i -> map.merge(i, a[i] == null ? identity : a[i], operator)),
        (m1, m2) -> {
            m2.forEach((k, v) -> m1.merge(k, v, operator));
            return m1;
        },
        map -> map.values().toArray(factory.apply(map.size())));
}

此收集器使用地图累积中间结果。

您可以按如下方式使用它:

Integer[] result = list.stream()
    .collect(reducingByColumn(0, Integer::sum, Integer[]::new));

答案 2 :(得分:13)

以下是使用流的解决方案:

final int SIZE = ...
List<Integer[]> arrays = ...
Integer[] result = IntStream.range(0, SIZE)
        .map(i -> arrays.stream()
                .map(arr -> arr[i])
                .filter(Objects::nonNull)
                .mapToInt(Integer::intValue)
                .sum())
        .boxed()
        .toArray(Integer[]::new);