二维数组的流运算

时间:2018-10-19 14:01:43

标签: java multidimensional-array lambda java-8 java-stream

我正在尝试从下面的二维数组中找到最佳的平均分数:

String[][] scores = { { "Amit", "70" }, { "Arthit", "60" }, { "Peter", "60" }, { "Arthit", "100" } };

输出为: 80(Arthit得分(60 + 100)/ 2)

到目前为止,我已经通过以下方法解决了这个问题,但是我正在寻找流的优雅解决方案:

public static void main(String[] args) {
        String[][] scores = { { "Amit", "70" }, { "Arthit", "60" }, { "Peter", "60" }, { "Arthit", "100" } };

        int highestAvg = Integer.MIN_VALUE;
        Function<String[], Integer> function = new Function<String[], Integer>() {
            @Override
            public Integer apply(String[] t) {
                int sum = 0, count = 0;
                for (int i = 0; i < scores.length; i++) {
                    if (t[0].equals(scores[i][0])) {
                        count++;
                        sum += Integer.parseInt(scores[i][1]);
                    }
                }
                int avg = sum / count;
                return highestAvg < avg ? avg : highestAvg;
            }
        };
        System.out.println(Arrays.stream(scores).map(function).max((o1, o2) -> o1.compareTo(o2)).get());
    }

请您提出建议,使用流处理二维数组的更好方法是什么?

注意:我不是在寻找确切的解决方案,只是在寻找您的宝贵建议。

3 个答案:

答案 0 :(得分:9)

您可以更多地使用内置的流功能,包括averaginggrouping收集器:

Stream.of(scores)
        .collect(
                Collectors.groupingBy(a -> a[0], 
                Collectors.averagingInt(a -> Integer.parseInt(a[1]))))
        .entrySet()
        .stream()
        .max(Entry.comparingByValue())
        .ifPresent(bestScore -> {
                String message = String.format("Best score is %s, by %s", bestScore.getValue(), bestScore.getKey());
                System.out.println(message);
        });

哪个打印Best score is 80.0, by Arthit

答案 1 :(得分:2)

我知道答案已经提交并已经接受,但是只是分享我在尝试回答您的问题时发现的内容。

Map<String, Double> collect = Arrays.stream(scores)
    .collect(Collectors.groupingBy(arr -> arr[0], 
             Collectors.averagingDouble(arr -> Integer.parseInt(arr[1]))));

这里key是他的名字,value是他的分数的平均值。现在,您可以遍历此地图以找到最大值,从而找到最大键的索引。

编辑:

要从地图中找到最大值,请使用:

Entry<String, Double> entry = collect.entrySet().stream()
         .max(Map.Entry.comparingByValue(Comparator.comparingDouble(e -> e.doubleValue())))
         .get();

答案 2 :(得分:2)

由于要获得的结果是最高的平均分数,因此您可以执行以下操作:

Collection<Double> values = Arrays.stream(scores)
                .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
                .values();

System.out.println(Collections.max(values));

这会流过scores多维数组,并使用groupingBy收集器按元素名称将元素累加成组,然后使用averagingInt作为下游收集器来获取平均值和然后最后使用Collections.max(values)来获得最佳的平均分数。

另一种方法:

double bestAverage = 
       Arrays.stream(scores)
             .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
             .values()
             .stream()
             .mapToDouble(Double::doubleValue)
             .max().getAsDouble();

System.out.println(bestAverage);

请注意,如果源为空,则上述两种方法都会导致异常,因此,如果要处理该异常,则可以使用isPresent或其他一些Optional方法,例如orElse等。

Arrays.stream(scores)
      .collect(groupingBy(a -> a[0], averagingInt(a -> Integer.parseInt(a[1]))))
      .values()
      .stream()
      .mapToDouble(Double::doubleValue)
      .max().ifPresent(v -> ...);

进口:

import java.util.stream.*;
import static java.util.stream.Collectors.*;