【问题标题】:Java Stream to aggregate list of JSONs into groupsJava Stream 将 JSON 列表聚合成组
【发布时间】:2021-09-07 08:18:33
【问题描述】:

我有 java 中的对象列表,像这样。

[
  {
    "applicationNumber": "100400",
    "users": "A",
    "category": "student"
  },
  {
    "applicationNumber": "100400",
    "users":"B",
    "category": "student"
  },
  {
    "applicationNumber": "100400",
    "users":"C",
    "category": "neighbour"
  },
  {
    "applicationNumber": "100400",
    "users": "D",
    "category": "neighbour"
  },
  {
    "applicationNumber": "200543",
    "users": "C",
    "category": "student"
  },
  {
    "applicationNumber": "200543",
    "users": "A",
    "category": "student"
  },
  {
    "applicationNumber": "200543",
    "users":"D",
    "category": "friend"
  }
]

我想将每个应用程序编号的每个类别的用户分组为列表(顺序无关紧要)。可以参考下面的json来了解一下。

[
  {
    "applicationNumber": "100400",
    "users": [
      "A",
      "B"
    ],
    "category": "student"
  },
  {
    "applicationNumber": "100400",
    "users": [
      "C",
      "D"
    ],
    "category": "neighbour"
  },
  {
    "applicationNumber": "200543",
    "users": [
      "C",
      "A"
    ],
    "category": "student"
  },
  {
    "applicationNumber": "200543",
    "users": [
      "D"
    ],
    "category": "friend"
  }
]

我可以使用 for 循环、HashMap 和 if else 条件来做到这一点。我想使用 Java 8 流来实现相同的 .谁能帮帮我,我是java新手。

PS:提前谢谢

【问题讨论】:

  • 能否提供一些Java 示例数据?
  • 我没有样本数据,因为我正在查询数据库并将其存储在 POJO 中。
  • 你使用 MongoDB 吗?如果是,您可以通过使用聚合管道docs.mongodb.com/manual/aggregation 来实现相同的目的
  • 不,我使用的是 Oracle 数据库。交互我正在使用 jparepository

标签: java spring spring-boot for-loop java-stream


【解决方案1】:

我认为在这里使用流有点过度设计,但您可以分两步完成。首先,您需要使用 Collectors.groupingBy() 将您的 pojos 分组到列表映射中。接下来,您需要使用 stream().reduce() 将每个列表缩减为单个值。

ObjectMapper mapper = new ObjectMapper()
        .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
List<Application> applications = Arrays.asList(mapper.readValue(json, Application[].class));
List<Application> groupedApplications = applications.stream()
        .collect(Collectors.groupingBy(ApplicationKey::of, Collectors.toList()))
        .values().stream()
        .map(apps -> apps.stream().reduce(Application::merge))
        .filter(Optional::isPresent)
        .map(Optional::get)
        .collect(Collectors.toList());

Application.java:

public class Application {
    private String applicationNumber;
    private String category;
    private List<String> users = new ArrayList<>();

    public static Application merge(Application first, Application second) {
        assert ApplicationKey.of(first).equals(ApplicationKey.of(second));
        Application merged = new Application(first.applicationNumber, first.category, first.getUsers());
        merged.users.addAll(second.getUsers());
        return merged;
    }
    //constructor, getters, setters
}

ApplicationKey.java

public class ApplicationKey {
    private String applicationNumber;
    private String category;

    public static ApplicationKey of(Application application) {
        return new ApplicationKey(application.getApplicationNumber(), application.getCategory());
    }

    public ApplicationKey(String applicationNumber, String category) {
        this.applicationNumber = applicationNumber;
        this.category = category;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        ApplicationKey that = (ApplicationKey) o;
        return Objects.equals(applicationNumber, that.applicationNumber) &&
                Objects.equals(category, that.category);
    }

    @Override
    public int hashCode() {
        return Objects.hash(applicationNumber, category);
    }

    //getters, setters
}

【讨论】:

  • 或者您可以尝试Collectors.collectingAndThen() 一步完成,但我认为这可能不太可读。
猜你喜欢
  • 1970-01-01
  • 2019-03-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-09-02
  • 2020-06-14
  • 2017-06-20
  • 2019-12-19
相关资源
最近更新 更多