按属性合并列表中的对象实例

Merging instances of objects in a list by attribute

我有一个对象 Person,它有 firstName、lastName 和 email

class Person {
   String firstname;
   String lastName;
   String email;
}

我有一个 Person 的列表,其中可能有多个 Persons 相同的 firstNamelastName 我想通过他们的电子邮件地址将它们合并一个分隔符。

即 人 A =

{
    "firstName": "David",
    "lastName": "Guiney",
    "email": "david.guiney@gmail.com"
}

B =

{
    "firstName": "David",
    "lastName": "Guiney",
    "email": "guiney.david@hotmail.com"
}

我希望将这些合并到

{
    "firstName": "David",
    "lastName": "Guiney",
    "email": "david.guiney@gmail.com;guiney.david@hotmail.com"
}

以便在我的列表中创建一个唯一的实例。

  1. 这取决于您将什么定义为唯一或相等。这可以通过 equals 和 hashCode 方法来表达。

  2. 您可以使用 java.util.stream.Collectors#toMap 方法提供合并功能并将您的列表映射到地图。在合并功能中,您可以实现应如何处理具有相同“键”的 2 个对象的逻辑。

    public class 人 { public 人(字符串名字,字符串姓氏,字符串电子邮件) { this.firstname = 名字; this.lastName = 姓氏; this.email = 电子邮件; }

     String firstname;
     String lastName;
     String email;
    
     @Override
     public boolean equals(Object o)
     {
         if (this == o)
         {
             return true;
         }
         if (o == null || getClass() != o.getClass())
         {
             return false;
         }
         Person person = (Person) o;
         return Objects.equals(firstname, person.firstname) && Objects.equals(lastName, person.lastName);
     }
    
     @Override
     public int hashCode()
     {
         return Objects.hash(firstname, lastName);
     }
    
     @Override
     public String toString()
     {
         return "Person{" +
             "firstname='" + firstname + '\'' +
             ", lastName='" + lastName + '\'' +
             ", email='" + email + '\'' +
             '}';
     }
    
     public static void main(String[] args)
     {
         List<Person> persons = Arrays.asList(new Person("David", "Guiney", "david.guiney@gmail.com"),
             new Person("David", "Guiney", "david.guiney@gmail.com"),
             new Person("Andreas", "Radauer", "please_no@spam.com")
         );
    
         Map<Integer, Person> uniquePersons =
             persons.stream()
                 .collect(Collectors.toMap(
                     Person::hashCode,
                     Function.identity(),
                     (person1, person2) -> {
                         person1.email = person1.email + ";" + person2.email; // this could be improved
                         return person1;
                     }
                 ));
    
         System.out.println(uniquePersons.values());
     }
    

    }

如果您不想为此用例使用 equals 和 hashCode,您当然可以提供自己的 getKey 逻辑

您可以将列表中的所有对象一一检查,但问题是时间复杂度。它将采用 O(n^2).

形式
for(int i=0;i<list.size();i++){
        for(int j=i+1;j<list.size();j++){
            if(list.get(i).firstName.equals(list.get(j).firstName) && list.get(i).lastName.equals(list.get(j).lastName)){
                list.get(i).email += ";"+list.get(j).email;
                list.remove(j);
            }
        }
    }

首先,如果一个人可以拥有多封电子邮件,我会在 Person class 中反映这一点,方法是让“电子邮件”属性存储电子邮件集合。

然后你可以使用Java 8个流。

public class Person {

private String firstName;

private String lastName;

private List<String> emails;// if a person is susceptible to have several emails, use a collection and not a single String

public Person(String firstName, String lastName, String email) {
    this.firstName = firstName;
    this.lastName = lastName;
    this.emails = new ArrayList<>();
    this.emails.add(email);
}

public static void main(String[] args) {
    List<Person> persons = Arrays.asList(
            new Person("David", "Guiney", "david.guiney@gmail.com"),
            new Person("Jean", "Patrick", "jp@pluton.com"),
            new Person("David", "Guiney", "david.guiney@hotmail.com"),
            new Person("Bruce", "Lee", "bl@kungfu.com")
    );

    // Group together the Person instances having the same firstname and same lastname
    Map<List<String>, Person> keyToPerson = persons.stream().collect(Collectors.toMap(
            p -> Arrays.asList(p.firstName, p.lastName),// define the key allowing to group person as the combination of firstname and lastname
            Function.identity(),// what is associated to the key. Here we want the Person instance itself
            (p1, p2) -> {// the logic to solve collision, i.e. instances having the same key
                p1.emails.addAll(p2.emails);// add the email(s) of the second instances in the email of the first instance
                return p1;
            }
    ));
    keyToPerson.values().forEach(p -> {
        System.out.println(p.firstName + " " + p.lastName + " (" + String.join("; ", p.emails) + ")");
    });
}

}

它应该像那样打印一些东西

David Guiney (david.guiney@gmail.com; david.guiney@hotmail.com)
Bruce Lee (bl@kungfu.com)
Jean Patrick (jp@pluton.com)

您还可以重新定义 Person 的 equals 和 hashcode 方法 class 来实现如何将 2 个实例组合在一起。