如何使用Java 8 Stream Map改写指定的Java业务代码?
用Java 8 Stream改写这段代码的正确方式
先明确原代码的核心逻辑:
- 遍历
item下的所有ItemPriceCode,查询匹配的厂商价格码并设置到ItemPriceCode中 - 移除标记为
DELETED的ItemPriceCode - 返回修改后的
item
你之前用map改不对,是因为Stream.map的作用是转换生成新元素,而原代码是直接修改原集合里的ItemPriceCode对象状态,这是典型的「副作用操作」,适合用forEach来处理,而非map。
下面是两种可行的改写方式:
方式一:用forEach处理修改,保留removeIf做过滤
这种写法和原逻辑最接近,只是把for循环换成Stream的forEach:
private Item getItemManufacturerPriceCodes(Item item) { // 遍历并修改每个ItemPriceCode的厂商价格码 item.getItemPriceCodes().stream() .forEach(ipc -> { Optional<ManufacturerPriceCodes> mpc = manufacturerPriceCodesRepository .findByManufacturerIDAndPriceCodeAndRecordDeleted( item.getManufacturerID(), ipc.getPriceCode(), NOT_DELETED ); mpc.ifPresent(manufacturerPriceCode -> ipc.setManufacturerPriceCode(manufacturerPriceCode.getName()) ); }); // 移除已标记删除的元素(原代码的removeIf可以保留,本身就是Java 8新增的方法) item.getItemPriceCodes().removeIf(ipc -> DELETED.equals(ipc.getRecordDeleted())); return item; }
方式二:用Stream生成新列表(无副作用,更符合Stream设计理念)
如果想完全用Stream流程处理,不修改原集合元素,可以生成一个新的List<ItemPriceCode>替换原列表:
private Item getItemManufacturerPriceCodes(Item item) { List<ItemPriceCode> processedPriceCodes = item.getItemPriceCodes().stream() // 先处理每个元素,设置厂商价格码 .map(ipc -> { // 因为要修改对象,这里可以复制一个新的ItemPriceCode(避免修改原对象) ItemPriceCode newIpc = new ItemPriceCode(ipc); // 假设存在拷贝构造方法 Optional<ManufacturerPriceCodes> mpc = manufacturerPriceCodesRepository .findByManufacturerIDAndPriceCodeAndRecordDeleted( item.getManufacturerID(), ipc.getPriceCode(), NOT_DELETED ); mpc.ifPresent(mp -> newIpc.setManufacturerPriceCode(mp.getName())); return newIpc; }) // 过滤掉已删除的元素 .filter(ipc -> !DELETED.equals(ipc.getRecordDeleted())) .collect(Collectors.toList()); // 替换item里的价格码列表 item.setItemPriceCodes(processedPriceCodes); return item; }
额外提醒
第一种方式直接修改原对象,和原代码行为完全一致;第二种方式生成新对象,适合不希望修改原集合元素的场景(需要ItemPriceCode有拷贝构造或手动复制属性)。另外,数据库查询是IO操作,放在Stream的forEach或map里会触发多次查询,如果数据量较大,建议先批量收集所有priceCode,一次查询所有匹配的厂商价格码再做映射,避免N+1查询问题。
内容的提问来源于stack exchange,提问作者Njena
相关产品推荐
相关产品推荐

