版权声明:Yes, I still love you, let me accompany you around, staged an impossible love https://blog.csdn.net/bc_aptx4869/article/details/82881527
import java.math.BigDecimal;
import java.util.*;
import java.util.function.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public abstract class MyBaseTree implements BO,PO,Comparable<MyBaseTree> {
//根ID默认是0
//public static String DEFAULT_ROOT_ID = "0";
public static String SPLIT = "-";
public interface Property {
String value = "value";
String parentId = "parentId";
String path = "path";
String level = "level";
String enable = "enable";
}
//主键
private String value;
//父级类别
private String parentId;
//树结构编码,用于快速查找, 每一层由4位字符组成,用-分割
//如第一层:0001 第二层:0001-0001 第三层:0001-0001-0001
private String path;
//排序索引
private Long sortIndex;
//层级
private Integer level;
//是否启用
private Byte enable;
public String getValue() {
return value;
}
public void setValue(String value) {
this.value = value;
}
public String getParentId() {
return parentId;
}
public void setParentId(String parentId) {
this.parentId = parentId;
}
public String getPath() {
return path;
}
public void setPath(String path) {
this.path = path;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Long getSortIndex() {
return sortIndex;
}
public void setSortIndex(Long sortIndex) {
this.sortIndex = sortIndex;
}
public Byte getEnable() {
return enable;
}
public void setEnable(Byte enable) {
this.enable = enable;
}
public abstract <T extends MyBaseTree> List<T> getChildren() ;
public abstract void setChildren(List<? extends MyBaseTree> children);
public int compareTo(MyBaseTree support) {
if (support == null) return -1;
return Long.compare(getSortIndex() == null ? 0 : getSortIndex(), support.getSortIndex() == null ? 0 : support.getSortIndex());
}
itw_xuyt02 20:57:45
/**
* 根据path获取父节点的path
*
* @param path path
* @return 父节点path
*/
public static String getParentPath(String path) {
if (path == null || path.length() < 4) return null;
return path.substring(0, path.length() - 5);
}
/**
* 将树形结构转为列表结构,并填充对应的数据。<br>
* 如树结构数据: {name:'父节点',children:[{name:'子节点1'},{name:'子节点2'}]}<br>
* 解析后:[{id:'id1',name:'父节点',path:'<b>aoSt</b>'},{id:'id2',name:'子节点1',path:'<b>aoSt</b>-oS5a'},{id:'id3',name:'子节点2',path:'<b>aoSt</b>-uGpM'}]
*
* @param parent 树结构的根节点
* @param target 目标集合,转换后的数据将直接添加({@link List#add(Object)})到这个集合.
* @param <T> 继承{@link MyBaseTree}的类型
*/
public static <T extends MyBaseTree> void expandTree2List(T parent, List<T> target) {
//包含自身
target.add(parent);
//设置主键
String pid = parent.getValue();
if (pid == null) {
pid = BasePO.createUID();
parent.setValue(pid);
}
//设置path
if (parent.getPath() == null) {
parent.setPath(parent.getValue());
}
//设置level
if (parent.getPath() != null && parent.getLevel() == null) {
parent.setLevel(parent.getPath().split(SPLIT).length);
}
//设置sortIndex
Long parentIndex = parent.getSortIndex();
if (null == parentIndex) {
parent.setSortIndex(IdHelper.genLongWorkerId());
}
//处理子孙
List<T> children = parent.getChildren();
if (children != null) {
for (int i = 0; i < children.size(); i++) {
T child = children.get(i);
if(StringHelper.isEmpty(child.getValue())){
child.setValue(BasePO.createUID());
}
//
if (child instanceof MyBaseTree && parent instanceof MyBaseTree) {
((MyBaseTree)child).setSortIndex(new BigDecimal(parentIndex + "0" + (i + 1)).longValue());
}
child.setParentId(pid);
//路径为父亲path-父亲ID
child.setPath (parent.getPath() + SPLIT + child.getValue());
child.setLevel(child.getPath().split(SPLIT).length);
expandTree2List(child, target);
}
}
}
itw_xuyt02 20:59:48
//递归的消费某棵树
public static <T extends MyBaseTree> void forEach(Collection<T> list, Consumer<T> consumer ) {
list.forEach(node -> {
consumer.accept(node);
if (node.getChildren() != null) {
forEach( node.getChildren(), consumer );
}
});
}
/**
* 集合转为树形结构,返回根节点集合
*
* @param dataList 需要转换的集合
* @param childConsumer 设置子节点回调
* @param <N> 树节点类型
* @return 树形结构集合
*/
public static <N extends MyBaseTree> List<N> list2tree(final Collection<N> dataList,
final BiConsumer<N, List<N>> childConsumer) {
return list2tree(dataList, childConsumer, (Function<TreeHelper<N>, Predicate<N>>) predicate -> node -> node == null || predicate.getNode(node.getParentId()) == null);
}
public static <N extends MyBaseTree> List<N> list2tree(final Collection<N> dataList,
final BiConsumer<N, List<N>> childConsumer,
final Predicate<N> rootNodePredicate) {
return list2tree(dataList, childConsumer, (Function<TreeHelper<N>, Predicate<N>>) predicate -> rootNodePredicate);
}
/**
* 列表结构转为树结构,并返回根节点集合
*
* @param dataList 数据集合
* @param childConsumer 子节点消费接口,用于设置子节点
* @param predicateFunction 根节点判断函数,传入helper,获取一个判断是否为跟节点的函数
* @param <N> 元素类型
* @return 根节点集合
*/
public static <N extends MyBaseTree> List<N> list2tree(final Collection<N> dataList,
final BiConsumer<N, List<N>> childConsumer,
final Function<TreeHelper<N>, Predicate<N>> predicateFunction) {
if(dataList == null || dataList.isEmpty()){
return new ArrayList();
}
//Objects.requireNonNull(dataList, "source list can not be null");
Objects.requireNonNull(childConsumer, "child consumer can not be null");
Objects.requireNonNull(predicateFunction, "root predicate function can not be null");
Supplier<Stream<N>> streamSupplier = () -> dataList.size() < 1000 ? dataList.stream() : dataList.parallelStream();
// id,node
Map<String,N> cache = new HashMap<>();
// parentId,children
Map<String,List<N>> treeCache = streamSupplier.get()
.peek(node -> cache.put(node.getValue(), node))
.collect(Collectors.groupingBy(MyBaseTree::getParentId));
Predicate<N> rootNodePredicate = predicateFunction.apply(new TreeHelper<N>() {
@Override
public List<N> getChildren(String parentId) {
return treeCache.get(parentId);
}
@Override
public N getNode(String id) {
return cache.get(id);
}
});
Stream<N> qwe = streamSupplier.get();
qwe.forEach(
node -> node.getValue()//1112
);
List<N> qwzxce = treeCache.get("1112");
return streamSupplier.get()
//设置每个节点的子节点
.peek(node -> childConsumer.accept(node, null !=treeCache.get(node.getValue())?treeCache.get(node.getValue()):null ))
//获取根节点
.filter(rootNodePredicate)
.collect(Collectors.toList());
}
itw_xuyt02 21:00:18
/**
* 树结构Helper
*
* @param <T> 节点类型
*/
interface TreeHelper<T> {
/**
* 根据主键获取子节点
*
* @param parentId 节点ID
* @return 子节点集合
*/
List<T> getChildren(String parentId);
/**
* 根据id获取节点
*
* @param id 节点ID
* @return 节点
*/
T getNode(String id);
}
}
调用时:
List<OrgTreeVO> orgTreeVOS = MyBaseTree.list2tree(orgTreeVOList, OrgTreeVO::setChildren, (Predicate<OrgTreeVO>) menuEntity ->
// parentId为空或者为-1的菜单则认为是根菜单
menuEntity.getParentId() == null || "".equals(menuEntity.getParentId()));
其中返回的VO类必须继承MyBaseTree.java文件:
public class OrgTreeVO extends MyBaseTree