Как фильтровать и комбинировать объекты, если они имеют одинаковые поля - PullRequest
2 голосов
/ 16 мая 2019

Я пытался решить проблему и застрял.У меня есть класс User:

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"));

Но этот список содержит повторяющиеся объекты с разницей только в группе.Поэтому мне нужно объединить дубликаты объектов, чтобы новый объект выглядел следующим образом:

Пользователь: имя: «Макс», электронная почта: «тест @ тест», возраст: 20, группы: «n1, n5»

Пользователь: имя: "Джон", электронная почта: "список @ тест", возраст: 21, группы: "n2"

Пользователь: имя: "Нэнси", электронная почта: "must @ test"", возраст: 22 года, группы:" n3, n4 "

Я понимаю, что мне нужно использовать пары из Java 8, но не понимаю, как именно.

Пожалуйста,помощь

Ответы [ 3 ]

2 голосов
/ 17 мая 2019

вы можете воспользоваться 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())));
1 голос
/ 16 мая 2019

Вы можете просто сделать:

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]
]

Обязательно добавьте геттеры и сеттеры, а также переопределите toString() пользователя.

1 голос
/ 16 мая 2019

Это рабочий пример того, что вам нужно (надеюсь:)).

Рассматривает комбинацию первых 3 полей как уникальный ключ. Затем он проходит по списку и добавляет пользователей на карту на основе ключа и группы в качестве значения. Я использую карту, потому что это делает поиск быстрее. Прежде чем вставить нового пользователя, я проверяю, есть ли он уже на карте. Если это так, я добавляю новую группу. Если это не так, я вставляю его с текущей группой.

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;
    }

}
...