Java 8:使用Stream还是更简便的解决方案?
我来帮你搞定List<ModelA>转List<ModelB>的问题!先把你没写完的ModelB补全(方便后续演示),然后给你几种实用的实现方式,按需选就行:
首先补全ModelB的代码(加了构造器和 getter):
class ModelB { private Long id; private Map<String, Integer> valuesByName; public ModelB(Long id, Map<String, Integer> valuesByName) { this.id = id; this.valuesByName = valuesByName; } public Long getId() { return id; } public Map<String, Integer> getValuesByName() { return valuesByName; } }
方法1:Java 8+ Stream API(按ID分组合并)
如果你的需求是把相同ID的ModelA实例合并到同一个ModelB中,用name作为Map的key,value作为对应的值,那Stream的分组功能简直量身定做:
import java.util.List; import java.util.Map; import java.util.stream.Collectors; public class ModelConverter { public static List<ModelB> convertList(List<ModelA> modelAList) { return modelAList.stream() // 第一步:按ID分组,key是id,value是同id下的所有ModelA .collect(Collectors.groupingBy(ModelA::getId)) .entrySet() .stream() // 第二步:把每个分组转成ModelB .map(entry -> new ModelB( entry.getKey(), entry.getValue().stream() .collect(Collectors.toMap(ModelA::getName, ModelA::getValue)) )) .collect(Collectors.toList()); } }
⚠️ 小提醒:如果同一个ID下有重复的name,toMap会抛IllegalStateException,可以加个冲突处理逻辑,比如保留第一个值:
Collectors.toMap(ModelA::getName, ModelA::getValue, (existingVal, newVal) -> existingVal)
方法2:传统循环实现(适合不习惯Stream的场景)
要是你更偏爱传统循环,逻辑同样清晰易懂:
import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class ModelConverter { public static List<ModelB> convertList(List<ModelA> modelAList) { // 先按ID收集所有name-value对 Map<Long, Map<String, Integer>> idToValuesMap = new HashMap<>(); for (ModelA modelA : modelAList) { // 没有对应ID的Map就新建一个,然后放入name-value idToValuesMap.computeIfAbsent(modelA.getId(), k -> new HashMap<>()) .put(modelA.getName(), modelA.getValue()); } // 把收集好的Map转换成ModelB列表 List<ModelB> modelBList = new ArrayList<>(); for (Map.Entry<Long, Map<String, Integer>> entry : idToValuesMap.entrySet()) { modelBList.add(new ModelB(entry.getKey(), entry.getValue())); } return modelBList; } }
方法3:用MapStruct简化(企业级项目常用)
如果你的项目已经在用MapStruct(一款流行的对象映射框架),可以用注解简化转换流程。先加Maven依赖:
<dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct</artifactId> <version>1.5.5.Final</version> </dependency> <dependency> <groupId>org.mapstruct</groupId> <artifactId>mapstruct-processor</artifactId> <version>1.5.5.Final</version> <scope>provided</scope> </dependency>
然后定义转换器接口:
import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.stream.Collectors; @Mapper public interface ModelMapper { ModelMapper INSTANCE = Mappers.getMapper(ModelMapper.class); // 单个ModelA转成Map<String, Integer> default Map<String, Integer> modelAToValuesMap(ModelA modelA) { Map<String, Integer> map = new HashMap<>(); map.put(modelA.getName(), modelA.getValue()); return map; } // 实现分组转换的逻辑 default List<ModelB> convertList(List<ModelA> modelAList) { return modelAList.stream() .collect(Collectors.groupingBy(ModelA::getId)) .entrySet() .stream() .map(entry -> new ModelB( entry.getKey(), entry.getValue().stream() .flatMap(a -> modelAToValuesMap(a).entrySet().stream()) .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue, (e1, e2) -> e1)) )) .collect(Collectors.toList()); } }
使用时直接调用:
List<ModelB> modelBList = ModelMapper.INSTANCE.convertList(modelAList);
如果你的需求不是按ID分组,而是每个ModelA单独转成一个ModelB(每个ModelB的ID和原ModelA一致,valuesByName只包含当前ModelA的name-value对),那逻辑更简单:
List<ModelB> modelBList = modelAList.stream() .map(a -> { Map<String, Integer> valuesMap = new HashMap<>(); valuesMap.put(a.getName(), a.getValue()); return new ModelB(a.getId(), valuesMap); }) .collect(Collectors.toList());
你可以根据实际业务场景挑合适的方式用~
内容的提问来源于stack exchange,提问作者Sunflame
相关产品推荐
相关产品推荐

