Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

handle duplicate key in Collectors.toMap() function

I am creating a map which its (key,value) will be (name, address) in my Person object:

Map<String, String> myMap = persons.stream.collect(Collector.toMap(person.getName(), person.getAddress(), (address1, address2) -> address1));

In the duplicate key situation, I would like to skip to add the second address to the map and would like to log the name also. Skipping the duplicate address I can do already using mergeFunction, but in oder to log the name I need in this mergeFunction the person object, something like:

(address1, address2) -> {
                           System.out.println("duplicate "+person.name() + " is found!");
                           return address1;
                        }

I am getting stuck by passing person object to this merge function.

like image 271
Bali Avatar asked Jan 10 '19 15:01

Bali


2 Answers

@Aomine: solution looks good and works for me too. Just wanted to confirm that with this it iterates twice right ?? Cause with simple solution like below it iterates only once but achieve what is required.

Map<String,String> myMap= new HashMap<>();
persons.stream().foreach(item-> {
    if(myMap.containsKey(item.getName()))
        {/*do something*/}
    else 
        myMap.put(item.getName(),item.getAddress());
});
like image 139
ygbgames Avatar answered Sep 18 '22 18:09

ygbgames


I believe the forEach approach along with Map.merge would be much simpler and appropriate for the current use case :

Map<String, String> myMap = new HashMap<>();
persons.forEach(person -> myMap.merge(person.getName(), person.getAddress(), (adrs1, adrs2) -> {
    System.out.println("duplicate " + person.getName() + " is found!");
    return adrs1;
}));

Note: Map.merge also uses BiFunction (parent of BinaryOperator as used in toMap), hence you could correlate the merge function here to your existing desired functionality easily.

like image 31
Naman Avatar answered Sep 19 '22 18:09

Naman