Skip to content
Advertisement

Merging instances of objects in a list by attribute

I have an object Person which has firstName, lastName and email

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

I have a list of Person where there are potentially multiple Persons of the same firstName and lastName and I want to merge these by their email address with a delimiter.

i.e. Person A =

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

Person B =

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

And I want these to be merged into

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

So as to create a unique instance in my list.

Advertisement

Answer

  1. It depends what you define as unique or equal. This could then be expressed by the equals and hashCode Method.

  2. you can use the java.util.stream.Collectors#toMap Method to provide a merge function and map your list to a map. In the merge function you can implement the logic how 2 objects with the same “key” should be handled.

    public class Person { public Person(String firstname, String lastName, String email) { this.firstname = firstname; this.lastName = lastName; this.email = 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());
     }
    

    }

If you don’t want to use equals and hashCode for this usecase you can of course just provide an own getKey Logic

User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement