java List数据封装Tree结构(代码简洁、高效率)
- 阐述说明
- 该工具主要有以下几个特点
- 工具相关源码
- Tree的Node节点:该节点属性是按照vue的antd ui组件tree树属性进行设置,可以根据运用情况进行修改相关属性,或者使用继承方式也可以
- Tree封装工具:该工具提供两种方式调用,可以根据个人喜好来选择
- 调用方式:比较简单灵活,可以将数据查询到的相关list传值到该工具中,即可封装为Tree结构了
阐述说明
该工具主要有以下几个特点
- 不使用递归: 该工具将list封装为tree结果的过程中,完成不涉及到递归方式来进行操作封装,借用map方式进行获取操作节点,避免树层级过多时嵌套多个循环来进行操作封装,该方式可以高效率完成节点封装为Tree树结构
- 使用lambda表达式: 工具中运用到了java8的新特性lambda表达式,主要的好处是可以很灵活接收各种list对象集合,可以对象属性情况解析为Tree的node节点对象,还有就是可以快速进行集合操作
- 代码简洁: 该工具不仅仅是可以高效率进行封装为Tree树结构,更重要的是,其代码简洁,运用方便,值得大家去借鉴和使用
工具相关源码
Tree的Node节点:该节点属性是按照vue的antd ui组件tree树属性进行设置,可以根据运用情况进行修改相关属性,或者使用继承方式也可以
import lombok.Data;
import java.util.ArrayList;
import java.util.List;
/**
* a-tree树节点
* @param <T>
*/
@Data
public class TreeNode<T> {
public TreeNode() {
}
public TreeNode(T node, String key, String title, String parentKey) {
this.node = node;
this.key = key;
this.title = title;
this.parentKey = parentKey;
}
/**
* 节点对象
*/
private T node;
/**
* a-tree树key
*/
private String key;
/**
* a-tree树标题
*/
private String title;
/**
* a-tree树父节点key
*/
private String parentKey;
/**
* a-tree树子节点
*/
private List<TreeNode<T>> children = new ArrayList<>();
}
Tree封装工具:该工具提供两种方式调用,可以根据个人喜好来选择
import org.test.entity.TreeNode;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
/**
* a-tree树工具
*/
public class TreeUtil {
/**
* List集合转为a-tree树状数据(调用方式一)
* @param list 需要转为树状的集合
* @param toTreeNode 对象转为TreeNode节点Function
* @return
*/
public static<T> List<TreeNode<T>> getTreeList(List<T> list, Function<T, TreeNode<T>> toTreeNode){
//对象--封装-->树节点
List<TreeNode<T>> treeNodeList = list.stream().map(toTreeNode).collect(Collectors.toList());
return nodeToTree(treeNodeList);
}
/**
* List集合转为a-tree树状数据(调用方式二)
* @param list 需要转为树状的集合
* @param key TreeNode的key对应对象的属性
* @param title TreeNode的title对应对象的属性
* @param parentKey TreeNode的parentKey对应对象的属性
* @return
*/
public static<T> List<TreeNode<T>> getTreeList(List<T> list, Function<T, String> key,Function<T,String> title,Function<T,String> parentKey){
List<String> keys = list.stream().map(key).collect(Collectors.toList());
List<String> titles = list.stream().map(title).collect(Collectors.toList());
List<String> parentKeys = list.stream().map(parentKey).collect(Collectors.toList());
//对象--封装-->树节点
List<TreeNode<T>> treeNodeList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
TreeNode<T> treeNode = new TreeNode<>(list.get(i),keys.get(i),titles.get(i),parentKeys.get(i));
treeNodeList.add(treeNode);
}
return nodeToTree(treeNodeList);
}
/**
* 把list节点封装为树状数据
* @param treeNodeList 需要转为tree树状的list集合
* @param <T>
* @return
*/
private static<T> List<TreeNode<T>> nodeToTree(List<TreeNode<T>> treeNodeList){
//把list对象存储到map中,方便后面用于树状拼接
Map<String,TreeNode<T>> treeNodeMap = treeNodeList.stream().collect(Collectors.toMap(TreeNode::getKey,i->i));
//连接树节点,封装为树状
List<TreeNode<T>> data = new ArrayList<>();
treeNodeList.forEach(val->{
String pk = val.getParentKey();
TreeNode<T> parent = treeNodeMap.get(pk);
if(parent == null){
//该节点为顶级节点,直接添加到返回数据中
data.add(val);
}else {
//该节点有父节点,则需添加到其父节点的子节点中
parent.getChildren().add(val);
}
});
return data;
}
}
调用方式:比较简单灵活,可以将数据查询到的相关list传值到该工具中,即可封装为Tree结构了
/**
* 模拟需要封装的实体
*/
@Data
class Demo{
private String id;
private String name;
private String parentId;
}
public static void main(String[] args) {
List<Demo> list = new ArrayList<>();//模拟数据库查询到的相关数据
TreeUtil.getTreeList(list, Demo::getId,Demo::getName,Demo::getParentId);//调用方式一
TreeUtil.getTreeList(list,i->new TreeNode<>(i,i.getId(),i.getName(),i.getParentId())); //调用方式二
}