很多时候为满足前后端交互的数据结构需求,往往我们需要把平铺的 List
数据与 Tree
型层级数据结构进行互转,这篇文章提供详实的递归和非递归的方式去实现数据结构转换,为了使用到 lambda
的特性, Java version >=8
。
需求
我们从基础设施层获取了一个列表数据,列表其中的对象结构如下,注意约束条件如果没有 pid
,默认为 null
。
@Getter @Setter @ToString @Builder public class NodeEntity { /** * id */ private Long id; /** * 父id */ private Long pid; } 复制代码
现在我们要将 List<NodeEntity>
数据,按照属性 pid
进行Tree型层级封装,并且支持多层级封装。一般很容易想到递归的实现方法,接下来这篇文章使用一套通用的解决办法,非递归实现结构转换。
实践List to Tree
递归实现
首先定义通用的Tree形数据接口。
public interface INodeDTO { /** * id * @return id */ public Long getId(); /** * pid * @return pid */ public Long getPid(); /** * 获取Children * @return Children */ public List<INodeDTO> getChildren(); /** * 设置children * @param children children */ public void setChildren(List<INodeDTO> children); } 复制代码
每个方法接口有详细的注释,无需多说。然后提供通用的转换 Function
。
/** * 非递归实现平铺数据转成Tree型结构 */ static final Function<List<INodeDTO>,List<INodeDTO>> MULTI_TREE_CONVERTER = sources-> sources.stream() .filter(item->{ item.setChildren( sources.stream() .filter(e-> Objects.equals(e.getPid(), item.getId())) .collect(Collectors.toList())); return item.getPid() == null;}) .collect(Collectors.toList()); 复制代码
我们利用对象引用,浅拷贝的原理,通过循环查找来组装层级,最后根据 pid==null
的数据一定是Tree型第一层的数据的条件进行过滤,筛选出第一层的数据组合成新的列表,达到目的。
非递归实现
//Establ