组合模式中使用flatMap实现容器扁平化的报错问题
嵌套Box容器扁平化问题及报错解决
问题背景
我正在学习设计模式,定义了Box接口,实现类包括Leaf(叶子节点)和BoxContainer(容器节点),并创建了多层嵌套的容器结构:
List<Box> boxContainer = new BoxContainer(new Leaf("red","fresh"), new Leaf("white","dry"), new Leaf("black","dry"), new Leaf("green", "fresh"), new BoxContainer(new Leaf("red","fresh"), new Leaf("white","dry"), new Leaf("black","dry"), new Leaf("green", "fresh")));
当前统计容器大小得到的是5,但实际内部有8个Leaf节点(外层4个,内层嵌套容器里还有4个)。我想用flatMap实现多层嵌套的扁平化,但尝试以下代码时出现**"Non-static method cannot be referenced from a static context"**错误:
List<Box> getBoxes() { List<Box> flat = allBoxes.stream().flatMap(List::stream).collect(Collectors.toList()); }
相关类定义:
class BoxContainer implements Box{ List<Box> allBoxes= new ArrayList<>(); String color; String state; public BoxContainer(Box... boxes) { allBoxes.addAll(Arrays.asList(boxes)); } }
interface Box { String getColor(); String getState(); }
报错原因分析
List::stream的错误引用:flatMap需要的是将流中元素转换为另一个流的函数,你直接用List::stream相当于试图调用List的非静态方法stream(),但流中的元素是Box类型而非List,类型不匹配导致报错。- 缺少递归逻辑:单层
flatMap只能处理一层嵌套,无法递归遍历多层嵌套的BoxContainer。
解决方案
步骤1:给Box接口添加递归扁平化方法
在Box接口中定义返回自身所有叶子节点流的方法,让不同实现类各自实现:
import java.util.stream.Stream; interface Box { String getColor(); String getState(); // 新增方法:返回当前Box包含的所有Leaf节点的流(递归处理嵌套) Stream<Leaf> flatten(); }
步骤2:实现Leaf的扁平化方法
Leaf是叶子节点,直接返回包含自身的流:
class Leaf implements Box { private String color; private String state; public Leaf(String color, String state) { this.color = color; this.state = state; } @Override public String getColor() { return color; } @Override public String getState() { return state; } @Override public Stream<Leaf> flatten() { return Stream.of(this); } }
步骤3:实现BoxContainer的扁平化方法
BoxContainer需要递归调用每个子Box的flatten()方法,再用flatMap合并所有流:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; class BoxContainer implements Box{ List<Box> allBoxes= new ArrayList<>(); String color; String state; public BoxContainer(Box... boxes) { allBoxes.addAll(Arrays.asList(boxes)); } @Override public String getColor() { return color; } @Override public String getState() { return state; } @Override public Stream<Leaf> flatten() { // 递归扁平化每个子Box,合并所有Leaf流 return allBoxes.stream() .flatMap(Box::flatten); } }
步骤4:获取所有Leaf节点
现在可以直接调用顶层BoxContainer的flatten()方法,收集为列表:
import java.util.List; import java.util.stream.Collectors; public class Main { public static void main(String[] args) { BoxContainer container = new BoxContainer(new Leaf("red","fresh"), new Leaf("white","dry"), new Leaf("black","dry"), new Leaf("green", "fresh"), new BoxContainer(new Leaf("red","fresh"), new Leaf("white","dry"), new Leaf("black","dry"), new Leaf("green", "fresh"))); // 获取所有Leaf List<Leaf> allLeaves = container.flatten().collect(Collectors.toList()); System.out.println(allLeaves.size()); // 输出8,符合预期 } }
原报错的临时修复(仅支持单层嵌套)
如果只是临时修复原代码的报错(但无法处理多层嵌套),需要判断每个Box是否为BoxContainer,再转换为流:
// 仅处理单层嵌套的写法(不支持多层) List<Box> getBoxes() { return allBoxes.stream() .flatMap(box -> { if (box instanceof BoxContainer) { return ((BoxContainer) box).allBoxes.stream(); } else { return Stream.of(box); } }) .collect(Collectors.toList()); }
但这种写法无法处理多层嵌套,推荐使用前面的递归实现方案。
内容的提问来源于stack exchange,提问作者Bajter
相关产品推荐
相关产品推荐

