如何使用Java Stream获取层级结构中的全量下属员工列表
实现前提
首先为Manager类添加subordinates的公共访问方法,避免直接暴露内部字段:
public List<Employee> getSubordinates() { // 返回不可变集合防止外部误改内部状态,不需要的话可以直接return subordinates; return Collections.unmodifiableList(subordinates); }
方案1:Java 9+ 无递归写法(广度优先遍历)
直接在Manager类中添加获取所有下属的方法,不需要额外辅助函数:
import java.util.function.Function; import java.util.stream.Stream; public List<Employee> getAllSubordinates() { return Stream.iterate( // 第一层:直接下属 getSubordinates().stream(), // 每层递归取出下属中所有Manager的直接下属,作为下一层 currentLayer -> currentLayer .filter(Manager.class::isInstance) .map(Manager.class::cast) .flatMap(Manager::getSubordinates) ) // 直到某一层没有下属为止停止遍历 .takeWhile(currentLayer -> currentLayer.findAny().isPresent()) // 把所有层的员工合并成一个流 .flatMap(Function.identity()) // 可选:防止层级结构出现循环引用导致重复数据/死循环,正常树结构可省略 .distinct() .toList(); }
方案2:Java 8兼容写法(深度优先遍历)
Java 8没有takeWhile方法,用递归实现层级展开:
import java.util.stream.Collectors; import java.util.stream.Stream; private Stream<Employee> flattenAllSubordinates(Employee employee) { if (employee instanceof Manager) { Manager manager = (Manager) employee; // 合并当前Manager的直接下属 + 所有下属的嵌套下属 return Stream.concat( manager.getSubordinates().stream(), manager.getSubordinates().stream().flatMap(this::flattenAllSubordinates) ); } // 普通员工没有下属,直接返回空流 return Stream.empty(); } public List<Employee> getAllSubordinates() { return flattenAllSubordinates(this) .distinct() .collect(Collectors.toList()); }
注意事项
- 不建议将
allSubordinates定义为固定的final成员变量:因为setManager方法会动态修改层级结构,固定字段会出现数据不一致的问题,每次调用方法动态计算更可靠。如果需要缓存结果,要在subordinates变更时清空缓存。 - 如果你的业务场景可能出现循环层级(比如误将下属设为上级的上级),必须保留
distinct(),或者额外通过员工ID的Set去重,避免死递归/重复数据。 - 层级特别深的场景下,递归写法可能出现栈溢出,建议换成迭代版的广度优先遍历实现。
内容的提问来源于stack exchange,提问作者Artsiom Siarheyeu
相关产品推荐
相关产品推荐

