如何使用带有对象列表的 java 8 流获取一些统计信息

How can I get some statistics using java 8 stream with object list

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

SqlResult(输入)

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

结果数据Class

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流API得到统计结果(val的平均值,成员数)?

您的代码失败的原因是您最终在 groupingBy 期间使用 [=15] 构造的 Map 上执行了 Map.getInteger 键=]s 在键集中。因此,查找中的相应 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());