Java8遍历List调用方法并聚合结果到Map的实现疑问
解决方案:遍历列表并聚合结果到同一Map
嗨,这个需求很常见!forEach确实因为返回void没法帮你收集结果,不过我们有几种简洁的方式实现遍历所有元素调用findAllUsers,并把所有结果合并到同一个Map里:
方法1:用flatMap先合并流再分组(最推荐)
这种方式最简洁,先把每个findAllUsers返回的列表拆成单个元素的流,再统一分组:
List<String> list = new ArrayList<>(); list.add("abcd"); list.add("afsd"); list.add("addd"); Map<String, List<Person>> ordersByInstrumentId = list.stream() // 遍历每个元素,调用服务方法并转成流 .flatMap(item -> findService.findAllUsers(item).stream()) // 按Dummy的id分组,自动合并相同key的结果 .collect(Collectors.groupingBy(Dummy::getId, Collectors.toList()));
原理:flatMap会把多个List<Person>的流“扁平化”成一个包含所有Person对象的单一流,之后的groupingBy就会把所有来源的Person按id统一分组,自然合并了不同item调用返回的结果。
方法2:用reduce合并多个分组后的Map
如果你希望先对每个item单独分组得到Map,再合并这些Map,可以用reduce:
Map<String, List<Person>> ordersByInstrumentId = list.stream() // 先对每个item调用方法并分组,得到单个分组Map .map(item -> findService.findAllUsers(item) .stream() .collect(Collectors.groupingBy(Dummy::getId, Collectors.toList()))) // 合并所有Map:把第二个Map的内容合并到第一个,相同key的List合并 .reduce(new HashMap<>(), (resultMap, currentMap) -> { currentMap.forEach((key, persons) -> resultMap.merge(key, persons, (existingList, newList) -> { List<Person> mergedList = new ArrayList<>(existingList); mergedList.addAll(newList); return mergedList; }) ); return resultMap; });
原理:reduce的第一个参数是初始空Map,之后每次把当前item生成的Map合并到结果Map中,merge方法负责处理相同key的情况,将两个List合并为一个。
方法3:传统循环实现(更直观)
如果你觉得Stream的写法不够直观,用普通循环也能轻松实现:
Map<String, List<Person>> ordersByInstrumentId = new HashMap<>(); for (String item : list) { List<Person> persons = findService.findAllUsers(item); for (Person person : persons) { String key = person.getId(); // 对应Dummy::getId,确保类型匹配 // 不存在key则创建新List,然后添加当前Person ordersByInstrumentId.computeIfAbsent(key, k -> new ArrayList<>()).add(person); } }
原理:外层循环遍历每个item调用服务方法,内层循环遍历返回的Person列表,用computeIfAbsent确保每个key对应一个List,然后把Person添加进去,逐步聚合所有结果。
内容的提问来源于stack exchange,提问作者Marinescu Raluca
相关产品推荐
相关产品推荐

