如何通过Stream API将嵌套列表数据转换为ProductDTO列表?
解决Stream API转换嵌套列表为ProductDTO列表的类型不匹配问题
你有一个结构为[[ID, 数量],[ID, 数量]]的嵌套字符串列表,需要将其转换为从数据库获取的ProductDTO对象列表,并把数量赋值给ProductDTO的description字段。使用普通循环可以实现,但用Stream API时出现类型不匹配错误,报错信息如下:
Required type: ProductDTO
Provided: Stream<org.greenway.backend.dto.ProductDTO>
错误的Stream实现代码
List<List<String>> listOfMap = new ArrayList<>(); // 数据为 [[25,1],[13,2],[30,1],[22,1]] List<ProductDTO> ordersList = new ArrayList<>(); listOfMap.forEach(s->ordersList.add(productService. getProductById(Long.valueOf(s.get(0))).stream(). peek(e->e.setDescription(s.get(1)))));
对应的正确循环实现
for (int i = 0; i < listOfMap.size(); i++){ ordersList.add(productService.getProductById(Long.valueOf(listOfMap.get(i).get(0))).orElseThrow()); ordersList.get(i).setDescription(listOfMap.get(i).get(1)); }
错误原因
你的错误在于:productService.getProductById(...)返回的是Optional<ProductDTO>,调用stream()后得到的是StreamordersList.add()需要的是单个ProductDTO对象,类型完全不匹配。另外peek是Stream的中间操作,不会触发流的执行,也不会将流转换为单个对象。
正确的Stream API实现
直接用stream()遍历嵌套列表,通过map将每个子列表转换为对应的ProductDTO,最后用collect收集成列表,完全符合函数式风格:
List<List<String>> listOfMap = new ArrayList<>(); // 数据为 [[25,1],[13,2],[30,1],[22,1]] List<ProductDTO> ordersList = listOfMap.stream() .map(subList -> { // 获取ID并查询ProductDTO,和循环里的orElseThrow保持一致 ProductDTO product = productService.getProductById(Long.valueOf(subList.get(0))) .orElseThrow(); // 设置description为数量 product.setDescription(subList.get(1)); return product; }) .collect(Collectors.toList());
代码解释
listOfMap.stream():将嵌套列表转换为流map(subList -> ...):将每个子列表映射为一个ProductDTO对象,逻辑和循环完全对应:- 从子列表取出ID,调用
getProductById获取ProductDTO(用orElseThrow()处理空值,和循环一致) - 将子列表中的数量赋值给
ProductDTO的description字段 - 返回处理后的
ProductDTO
- 从子列表取出ID,调用
collect(Collectors.toList()):将所有处理后的ProductDTO收集为列表
这样既满足了必须使用Stream API的要求,又解决了类型不匹配的问题,同时代码比原来的forEach加列表的写法更简洁、符合Stream的设计理念。
内容的提问来源于stack exchange,提问作者George
相关产品推荐
相关产品推荐

