处理Collectors.toMap()函数中的重复键

sch*_*hau 5 java hashmap java-8 java-stream

我正在创建一个地图,其(键,值)将在我的Person对象中(名称,地址):

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

在重复键情况下,我想跳过将第二个地址添加到地图中,并希望也记录该名称.跳过重复的地址我已经可以使用mergeFunction,但是在oder中记录我在这个mergeFunction中需要的名称person对象,如:

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

我通过将person对象传递给此合并函数而陷入困境.有人能给我一些提示吗?先谢谢你!

小智 6

@Aomine:解决方案看起来不错,也适合我.只是想确认一下这个迭代两次吧?由于下面的简单解决方案,它只迭代一次,但实现了所需要的.

Map<String,String> myMap= new HashMap<>();
persons.stream().foreach(item-> {
    if(myMap.containsKey(item.getName()))
        {/*do something*/}
    else 
        myMap.put(item.getName(),item.getAddress());
});
Run Code Online (Sandbox Code Playgroud)


Nam*_*man 6

我相信这种forEach方法Map.merge对于当前的用例来说会更简单和合适:

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;
}));
Run Code Online (Sandbox Code Playgroud)

:Map.merge也使用BiFunction(母公司BinaryOperator为使用toMap),因此,你可以在这里轻松地将相关功能合并到现有所需的功能.


Ous*_* D. 5

如果您想在合并函数中访问整个 person 对象,请Function.identity() 传递valueMapper

Map<String, Person> myMap = 
        persons.stream()
               .collect(toMap(p -> p.getName(), 
                      Function.identity(), // or p -> p
                     (p1, p2) -> { /* do logic */ }));
Run Code Online (Sandbox Code Playgroud)

但正如您所看到的,结果映射值是Person对象,如果您仍然想要Map<String, String>结果并且仍然访问整个Person对象,那么mergeFunction您可以执行以下操作:

 persons.stream()
         .collect(toMap(p -> p.getName(), Function.identity(),(p1, p2) -> { /* do logic */ }))
         .entrySet()
         .stream()
         .collect(toMap(Map.Entry::getKey, p -> p.getValue().getAddress()));
Run Code Online (Sandbox Code Playgroud)

  • @Aomine 抱歉我的打字错误。现在可以了,非常感谢您的帮助:) (2认同)