2787184
2787184

Reputation: 3881

Merge two objects List in Java

How to merge two user list, if user is common merge its attribute.

I have two user lists, getting first list from DB and second from web service, if their firstname and lastname are same then user merge attribute and return combined list.

import java.util.List;
import java.util.Objects;

 class User {
     String firstName;
     String lastName;
     Integer count;
     Integer marks;
     String status;

     @Override
     public boolean equals(Object o) {
         if (this == o) return true;
         if (!(o instanceof User)) return false;
         User user = (User) o;
         return Objects.equals(firstName, user.firstName) &&
                 Objects.equals(lastName, user.lastName);
     }

     @Override
     public int hashCode() {
         return Objects.hash(firstName, lastName);
     }

    //constructor getter setter....

 }




 public class MainTest {

     public static void main(String[] args) {

         List<User> source1 = List.of(new User("A", "A", 1, 0, null),
                 new User("B", "B", 2, 0, null),
                 new User("C", "C", 3, 0, null));

         List<User> source2 = List.of(new User("A", "A", 0, 10, "FAIL"),
                 new User("B", "B", 0, 20, "FAIL"),
                 new User("D", "D", 0, 30, "PASS"));


         List<User> combinedExpectedList = List.of(new User("A", "A", 1, 10, "FAIL"),
                 new User("B", "B", 2, 20, "FAIL"),
                 new User("C", "C", 3, 0, null),
                 new User("D", "D", 0, 30, "PASS"));

         //List<User> userList3= Stream.concat(source1.stream(), source2.stream()).distinct().collect(Collectors.toList());//Adding 4 records but marks and status not copied
         //BeanUtils.copyProperties(model2, model1); - can't user don't have library

         for (User t : source2) {
             for (User s : source1) {
                 if (t.getFirstName().equals(s.getFirstName()) && t.getLastName().equals(s.getLastName())) {
                     t.setCount(s.getCount());
                 }
             }
         }// Not adding record with firstName=C and LastName=C

         System.out.println(combinedExpectedList.equals(source2));
     }
 }

Upvotes: 1

Views: 243

Answers (2)

lczapski
lczapski

Reputation: 4120

Similar to this answer but here 'User' within source list remains unchanged:

List<User> values = new ArrayList<>(Stream.concat(source1.stream(), source2.stream())
        .collect(Collectors.toMap(e -> e.firstName + e.lastName, Function.identity(),
                (User u1, User u2) ->
                        new User(u1.firstName, u1.lastName, u1.count,
                                (u1.marks == 0) ? u2.marks : u1.marks,
                                (u1.status == null) ? u2.status : u1.status
                        )
        )).values());

Upvotes: 0

Vikas
Vikas

Reputation: 7165

Assuming that you want to retain non zero marks and non null status elements, you can not directly use distinct. You can use Collectors.toMap as below,

List<User> userList3 = Stream.concat(source1.stream(), source2.stream())
                .collect(Collectors.toMap(e -> e.firstName + e.lastName, e -> e,
                        (User u1, User u2) -> {
                            if (u1.marks == 0)
                                u1.marks = u2.marks;
                            if (u1.status == null)
                                u1.status = u2.status;
                            return u1;
                        })).values().stream().collect(Collectors.toList());

Note that you may need to reorder elements.

Upvotes: 3

Related Questions