Java 8 Stream收集为<String,Integer> Map集合的实现求助
解决Java 8 Stream收集到Map的问题
首先得指出你之前写法的核心问题:你在Collectors.toMap里的键映射函数写错了!name -> mapMethodNameConvention是把mapMethodNameConvention这个Function对象本身作为键,而不是映射后的字符串name,这就导致所有键都是同一个Function实例,完全不符合你想要的<String, Integer> Map需求。
下面给你两种符合要求的实现方式,你可以根据自己的习惯选择:
方式一:复用原有分流转逻辑(简单直观)
这种方式和你原来往List里加元素的逻辑最接近,只是把add换成put,同时指定对应的值:
// 先创建目标Map Map<String, Integer> methodNameMap = new HashMap<>(); // 处理fieldsMappersMetadata,对应值为2 typesMapperGenerationInput.getFieldsMappersMetadata().stream() .map(mapMethodNameConvention) .forEach(methodName -> methodNameMap.put(methodName, 2)); // 处理fieldsValueProducersMetadata,对应值为1 typesMapperGenerationInput.getFieldsValueProducersMetadata().stream() .map(produceMethodNameConvention) .forEach(methodName -> methodNameMap.put(methodName, 1)); // 处理constantMappingsMetadata,对应值为1 typesMapperGenerationInput.getConstantMappingsMetadata().stream() .map(setConstantValueMethodNameConvention) .forEach(methodName -> methodNameMap.put(methodName, 1));
如果遇到重复的方法名,后面的put会覆盖前面的值(比如如果某个方法名同时出现在fieldsMappers和其他来源里,最终值会是1)。如果你想保留优先级更高的2,可以把put换成putIfAbsent,这样只有当键不存在时才会放入:
.forEach(methodName -> methodNameMap.putIfAbsent(methodName, 2));
方式二:合并流后统一收集(更符合Stream风格)
如果你想用更纯粹的Stream链式操作,可以把三个流合并成一个,给每个元素带上对应的数值,再统一收集到Map:
Map<String, Integer> methodNameMap = Stream.concat( // 第一个流:映射为<方法名, 2>的Entry typesMapperGenerationInput.getFieldsMappersMetadata().stream() .map(mapMethodNameConvention) .map(name -> new AbstractMap.SimpleEntry<>(name, 2)), // 合并另外两个流,都映射为<方法名, 1>的Entry Stream.concat( typesMapperGenerationInput.getFieldsValueProducersMetadata().stream() .map(produceMethodNameConvention) .map(name -> new AbstractMap.SimpleEntry<>(name, 1)), typesMapperGenerationInput.getConstantMappingsMetadata().stream() .map(setConstantValueMethodNameConvention) .map(name -> new AbstractMap.SimpleEntry<>(name, 1)) ) ) .collect(Collectors.toMap( Map.Entry::getKey, // 用Entry的key作为Map的键 Map.Entry::getValue, // 用Entry的value作为Map的值 // 处理重复键:这里选择保留第一个出现的值(比如fieldsMappers的2会被保留) (existingValue, newValue) -> existingValue ));
这里的第三个参数是处理重复键的冲突逻辑,如果你想让后面出现的值覆盖前面的,就改成(existing, newVal) -> newVal即可。
内容的提问来源于stack exchange,提问作者Tali
相关产品推荐
相关产品推荐

