有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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

我有一个对象人,它有名字、姓氏和电子邮件

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

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


共 (3) 个答案

  1. # 1 楼答案

    首先,如果Person可以有多封电子邮件,我会在Person类中通过一个“emails”属性来存储电子邮件的集合来反映这一点

    然后可以使用Java8流

    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方法,以实现如何将2个实例分组在一起

  2. # 2 楼答案

    1. 这取决于您定义的唯一性或相等性。这可以用equals和hashCode方法表示

    2. 您可以使用java。util。流动收集器#toMap方法提供合并功能并将列表映射到映射。在merge函数中,您可以实现如何处理具有相同“键”的两个对象的逻辑

      公共阶层人士 { 公众人物(stringfirstname、stringlastname、stringemail) { 这名字=名字; 这lastName=lastName; 这电子邮件=电子邮件; }

       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逻辑

  3. # 3 楼答案

    您可以逐个检查列表中的所有对象,但问题在于时间复杂性。它将采用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);
                }
            }
        }