如何使用Java 8 Stream和对象列表获取一些统计信息

3

我有一个 List<SqlResult>。 我需要从 SqlResult 聚合得到一个 List<Result>,例如:

SqlResult(输入)

public class SqlResult{
  private String key1;
  private String key2;
  private Double val;
  // getters, setters and constructor

结果数据类

public class Result{
  private String key1;
  private String key2;
  private Double avgVal;
  private Long   count;
  // getters, setters and constructor


我希望获得以下形式的列表,按照key1、key2分组,成员数量为count,val的平均值为avgVal。 下面的代码会抛出NullPointerException异常。
public class Main 
{
  public static void main(String[] args) {
    List<SqlResult> listSqlResult = new ArrayList<>();
    listSqlResult.add(new SqlResult(a1,b1,123));
    listSqlResult.add(new SqlResult(a1,b1,10));
    listSqlResult.add(new SqlResult(a1,b1,23));
    listSqlResult.add(new SqlResult(a1,b2,3));
    listSqlResult.add(new SqlResult(a1,b2,73));
    listSqlResult.add(new SqlResult(a1,b2,15));
    listSqlResult.add(new SqlResult(a2,b1,43));
    listSqlResult.add(new SqlResult(a2,b1,19));
    listSqlResult.add(new SqlResult(a2,b1,15));
    listSqlResult.add(new SqlResult(a2,b2,38));
    listSqlResult.add(new SqlResult(a2,b2,73));
    listSqlResult.add(new SqlResult(a2,b2,15));

    List<Result> listResult = listSqlResult.stream
        .collect(groupingBy(SqlResult::getKey1,
                 groupingBy(SqlResult::getKey2))).values().stream()
        .map(e -> new Result(e.get(0).get(0).getKey1(), e.get(0).get(0).getKey2(),e.get(0).stream().mapToDouble(e::getValue).average(), e.get(0).stream().count()))
    .collect(Collectors.toList())
;

如何使用Java Stream API获取统计结果(val的平均值,member的数量)?

1个回答

4
你的代码失败的原因是你在一个 Map 上执行了带有 Integer 键的 Map.get,而该 Map 在 groupingBy 期间是用 String 构造键集的。因此,在查找过程中会有相应的 null 值,随后是 NPE。
如果你能将你的要求思考成两个步骤,就会更简单。一,总结你手头的数据。二,将其映射到你选择的所需结果对象。
借助现有的 Collectors.summarizing...,这可能看起来就像下面这样简单:
Map<List<String>, DoubleSummaryStatistics> groupedStatistics = listSqlResult.stream()
        .collect(Collectors.groupingBy(sr -> Arrays.asList(sr.getKey1(), sr.getKey2()),
                Collectors.summarizingDouble(SqlResult::getVal)));

List<Result> results = groupedStatistics.entrySet().stream()
        .map(e -> new Result(e.getKey().get(0), e.getKey().get(1),
                e.getValue().getAverage(), e.getValue().getCount()))
        .collect(Collectors.toList());

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接