Home > front end >  Compare two maps of Collections and filter out the same values
Compare two maps of Collections and filter out the same values

Time:08-10

I'm trying to compare two maps currMap and prevMap and merge the result to the new one. By comparing i need to filter out the keys and then values Person.getName() and Person.getSurname(). If prevMap already has the same Person.getName() and Person.getSurname() as currMap, these Collection wont be merged. For example:


    // {[Long: 1] : [[name:John, surname: Smith, age: 20, gender: m]]
    Map<Long, Collection<Person>> currMap;

   // {[Long: 1] : [[name:John, surname: Smith, age: 20, gender: m],
   //               [name: Sarah, surname: Smith, age:27, gender: f]]
    Map<Long, Collection<Person>> prevMap;

// {[Long: 1] : [[name: Sarah, surname: Smith, age:27, gender: f]]
    Map<Long, Collection<Person>> result;

I tried to do it like that.


Collection<Person> arr = new ArrayList();

for (Map.Entry<Long, Collection<Person>> currEntry : currMap.entrySet()) {
            for (Map.Entry<Long, Collection<Person>> prevEntry : prevMap.entrySet()) {

                for (Person currPerson : currEntry.getValue()) {
                    for (Person prevPerson : prevEntry.getValue()) {
                        if((!currPerson.getName().equals(prevPerson.getName()) 
                                && !currPerson.getSurname().equals(prevPerson.getSurname()))) {
                            arr.add(currPerson);
                            result.put(currEntry.getKey(), arr);
                        }
                    }
                }
            }
        }

return result;

I believe there is more efficient way to make it easier through streams. Any tips will be appreciated :) Thank you

CodePudding user response:

There is always a better solution than 4 nested loops:

    Map<Long, Collection<Person>> currMap = new HashMap<>();
    currMap.put(1L, Arrays.asList(new Person("John", "Smith", 20, 'm')));
    
    Map<Long, Collection<Person>> prevMap = new HashMap<>();
    prevMap.put(1L, Arrays.asList(new Person("John", "Smith", 20, 'm'), new Person("Sarah", "Smith", 27, 'f')));
    
    //Merge maps
    Map<Long, Collection<Person>> result = Stream.of(currMap, prevMap)
            .flatMap(m -> m.entrySet().stream())
            .collect(Collectors.toMap(
                            Map.Entry::getKey, 
                            Map.Entry::getValue,
                            (value1, value2) -> {
                                //you need to create duplicate collection, because removeAll modify collection 
                                Collection<Person> list1 = new ArrayList<>(value1);
                                Collection<Person> list2 = new ArrayList<>(value2);
  
                                //remove duplicates from collections
                                list1.removeIf(x -> value2.stream().anyMatch(p -> p.getName().equals(x.getName()) && p.getSurname().equals(x.getSurname()))); // second from first
                                list2.removeIf(x -> value1.stream().anyMatch(p -> p.getName().equals(x.getName()) && p.getSurname().equals(x.getSurname()))); // first from second
                                  
                                Collection<Person> valueOfDuplicateKeys = new ArrayList<>(list1);
                                valueOfDuplicateKeys.addAll(list2);
                                
                                return valueOfDuplicateKeys;
                            }
                    ));

ouput:

K: 1 V: [[name=Sarah, surname=Smith, age=27, gender=f]]

  • Related