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

标签 java java-8 java-stream aggregate groupingby

我有一个 List<SqlResult> .我需要一个 List<Result>来自 SqlResult 的聚合。例如,

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 的平均值,成员数)?

最佳答案

您的代码失败的原因是您最终使用 Integer 键在 Map 上执行 Map.get,在 >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());

关于java - 如何使用带有对象列表的 java 8 流获取一些统计信息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67903675/

相关文章:

java - 带有 setter/getter 的枚举

java - 如何在 Java 中使用 Stream 填充 HashMap<Long, Long>

java - 使用流进行从数组到列表的空安全转换

java - 将javascript对象数组作为参数发送到 Controller

java - Observable OnCompleted 无法更新 UI

java - 通过 Jackson 的 ZonedDateTime 往返产生不相等的 ZonedDateTime

java - 为什么 lambda 中的变量必须是最终的或实际上是最终的?

java - 使用方法参数查找数组最小值的优雅方法?

java - GWT-RPC 还是 RequestFactory 用于身份验证?

java - 使用 SXSSF Workbook 可以写入的行数