【问题标题】:How to filter and combine objects if they has same fields如果对象具有相同的字段,如何过滤和组合对象
【发布时间】:2019-10-03 15:32:25
【问题描述】:

我已尝试解决问题,但被卡住了。我有班级用户:

public class User {

   public String name;
   public String email;
   public Integer age;
   public String group;

   public User() {
   }

   public User(String name, String email, Integer age, String group) {
      this.name = name;
      this.email = email;
      this.age = age;
      this.group = group;
   }
}

用户列表如下:

List<User> users = new ArrayList<>();
users.add(new User("Max" , "test@test", 20 , "n1"));
users.add(new User("John" , "list@test", 21 , "n2"));
users.add(new User("Nancy" , "must@test", 22 , "n3"));
users.add(new User("Nancy" , "must@test", 22 , "n4"));
users.add(new User("Max" , "test@test", 20 , "n5"));

但此列表包含重复对象,仅在组中存在差异。所以我需要将重复的对象组合成新的对象看起来像:

用户:姓名:“Max”,电子邮件:“test@test”,年龄:20,组:“n1, n5”

用户:姓名:“John”,电子邮件:“list@test”,年龄:21,组:“n2”

用户:姓名:“Nancy”,电子邮件:“must@test”,年龄:22,组:“n3, n4”

我知道我需要使用 Java 8 中的 Steam,但不知道具体如何使用。

请帮忙

【问题讨论】:

  • 到目前为止你尝试了什么?
  • 我真的不认为 Streams 会在这里为您提供帮助。您的 Java 水平如何:您可以使用伪代码并自己实现它吗?您想要一个完整的解决方案吗?
  • 预期输出与给定描述不匹配。请edit帖子并更正它,以便更好地帮助您。另请参阅@Zabuza 的评论。图片不如实际代码有用。
  • 我建议为您的用户对象添加一个id 字段,以便轻松识别唯一用户。

标签: java list collections java-8 java-stream


【解决方案1】:

您可以利用toMap 收集器,因为它具有合并功能,可以加入您的重复对象,例如,每次找到重复对象时我都会创建一个新对象,但您可以修改现有对象

static User join(User a, User b) {
    return new User(a.getName(), a.getEmail(), a.getAge(), a.getGroup() + "," + b.getGroup());
}

和流操作。

List<User> collect = users.stream()
            .collect(Collectors.collectingAndThen(Collectors.toMap(User::getEmail,
                            Function.identity(), 
                            (a, b) -> join(a, b)),
                    map -> new ArrayList<>(map.values())));

【讨论】:

    【解决方案2】:

    你可以这样做:

    List<User> sortedUsers = new ArrayList<>();
    // group by email-id
    Map<String, List<User>> collectMap = 
                     users.stream().collect(Collectors.groupingBy(User::getEmail));
    
    collectMap.entrySet().forEach(e -> {
        String group = e.getValue().stream()                     // collect group names
                                   .map(i -> i.getGroup())
                                   .collect(Collectors.joining(","));
        User user = e.getValue().get(0);
        sortedUsers.add(new User(user.getName(), user.getEmail(), user.getAge(), group));
    });
    

    哪个输出:

    [
       User [name=John, email=list@test, age=21, group=n2], 
       User [name=Max, email=test@test, age=20, group=n1,n5], 
       User [name=Nancy, email=must@test, age=22, group=n3,n4]
    ]
    

    确保添加 getter 和 setter,同时覆盖 User 的 toString()

    【讨论】:

      【解决方案3】:

      这是您需要的一个工作示例(我希望 :))。

      它将前 3 个字段的组合视为唯一键。然后它遍历列表并根据键将用户添加到 Map 并将组作为值。我使用地图是因为它使检索更快。在插入新用户之前,我检查它是否已经在地图中。如果是,那么我追加新组。如果不是,我将其插入当前组。

      import java.util.ArrayList;
      import java.util.HashMap;
      import java.util.List;
      import java.util.Map;
      
      public class User {
      
          public String name;
          public String email;
          public Integer age;
          public String group;
      
          public static final void main(String[] args) {
              List<User> users = new ArrayList<>();
              users.add(new User("Max", "test@test", 20, "n1"));
              users.add(new User("John", "list@test", 21, "n2"));
              users.add(new User("Nancy", "must@test", 22, "n3"));
              users.add(new User("Nancy", "must@test", 22, "n4"));
              users.add(new User("Max", "test@test", 20, "n5"));
      
              List<User> filtered = filter(users);
              filtered.stream().forEach(System.out::println);
          }
      
          public User() {
          }
      
          public User(String key, String group) {
              String[] keys = key.split("-");
              this.name = keys[0];
              this.email = keys[1];
              this.age = Integer.parseInt(keys[2]);
              this.group = group;
          }
      
          public User(String name, String email, Integer age, String group) {
              this.name = name;
              this.email = email;
              this.age = age;
              this.group = group;
          }
      
          public String toString() {
              return name + " : " + email + " : " + " : " + age + " : " + group;
          }
      
          public String getUniqueKey() {
              return name + "-" + email + "-" + age;
          }
      
          public static List<User> filter(List<User> users) {
              Map<String, String> uniqueGroup = new HashMap<>();
              for (User user : users) {
                  String found = uniqueGroup.get(user.getUniqueKey());
                  if (null == found) {
                      uniqueGroup.put(user.getUniqueKey(), user.group);
                  } else {
                      uniqueGroup.put(user.getUniqueKey(), found + ", " + user.group);
                  }
              }
      
              List<User> newUsers = new ArrayList<>();
              for (String key : uniqueGroup.keySet()) {
                  newUsers.add(new User(key, uniqueGroup.get(key)));
              }
      
              return newUsers;
          }
      
      }
      

      【讨论】:

        猜你喜欢
        • 2012-04-03
        • 1970-01-01
        • 1970-01-01
        • 2020-06-16
        • 2021-10-27
        • 2019-10-03
        • 2012-08-07
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多