很多时候为满足前后端交互的数据结构需求,往往我们需要把平铺的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型第一层的数据的条件进行过滤,筛选出第一层的数据组合成新的列表,达到目的。
非递归实现
//Establish tree s