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]]