Java Combine two list with by removing duplicates

Viewed 667

I have two list

List<Map<String,Object>> list1 = new ArrayList<>();
List<Map<String,Object>> list2 = new ArrayList<>();

The list is a list of maps with each map like below

name-> XXX
age->yyy
id->zzz

Now I want to combine these into a single list and also removing duplicates based on the id of the map.

Im using the below to combine the list but not sure how to remove duplicates based on a value of the map

List<Map<String,Object>> newList = Stream.concat(list1.stream(), list2.stream()).collect(Collectors.toList());
3 Answers

You can create predicates closure with TreeMap to filter maps with unique "id"

static Predicate<Map<String, Object>> predicate() {
    var set = new TreeSet<>();
    return m -> set.add(m.get("id")); 
}
List<Map<String,Object>> list1 = new ArrayList<>();
List<Map<String,Object>> list2 = new ArrayList<>();
List<Map<String, Object>> newList = Stream.concat(list1.stream(), list2.stream())
                .filter(predicate())
                .collect(Collectors.toList());

This can be simpler using a map to manage unique IDs as keys:

// Use LinkedHashMap if order is needed
Map<Object, Map<String, Object>> megaMap = new HashMap<>();
Stream.concat(list1.stream(), list2.stream())
        .forEach(map -> megaMap.computeIfAbsent(map.get("id"), id -> map));

List<Map<String, Object>> newList = new ArrayList<>(megaMap.values());

The same map can be generated using Collectors.toMap():

Map<Object, Map<String, Object>> megaMap2 = Stream.concat(list1.stream(), list2.stream())
        .collect(Collectors.toMap(m -> m.get("id"), 
                                  Function.identity(), 
                                  (v1, v2) -> v1, 
                                  HashMap::new));
newList = new ArrayList<>(megaMap2.values());

You can use flatMap to flatten the list then use Collectors.toMap to group by map's id key and get then map's value in the new ArrayList

List<Map<String,Object>> newList = 
   new ArrayList<>(
       Stream.of(list1, list2)
            .flatMap(l -> l.stream())
            .collect(Collectors.toMap(m -> m.get("id"), e -> e, (a, b) -> a)).values());
Related