递归工具类
import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;
/**
* @author: ljp
* @description: 结构树工具类
* @date: 2022年5月25日 上午10:59:31
*/
public class TreeSelectUtil {
/**
* 将集合转化为结构树
*
* @param data 所有数据列表
* @return 结构树列表
*/
public static List<Tree> change(List<Tree> data) {
if (data == null || data.size() == 0) {
return Collections.emptyList();
}
// 先取出最上级
//这里判断上级id为空或为-1时时最上级
//部分数据递归时会有漏洞,下面会修复
List<Tree> list = data.stream().filter(d -> d.getParentId() == null || d.getParentId() == -1)
.collect(Collectors.toList());
// 递归取出下级
list = getLower(list, data);
return list;
}
/**
* 开始递归
*
* @param list 结构树列表
* @param data 总数据列表
* @return
*/
private static List<Tree> getLower(List<Tree> list, List<Tree> data) {
if (list == null || list.size() == 0) {
return Collections.emptyList();
}
for (Tree ts : list) {
// 递归下一级
List<Tree> lower = getLower(ts, data);
ts.setChildren(lower);
}
return list;
}
/**
* 遍历下一层
*
* @param up 上级对象
* @param data 总数据列表
* @return
*/
private static List<Tree> getLower(Tree up, List<Tree> data) {
//获取up的所有下级对象
List<Tree> collect = data.stream()
.filter(recursion -> up.getId().equals(recursion.getParentId()))
.collect(Collectors.toList());
if (collect == null || collect.size() == 0) {
return Collections.emptyList();
}
//遍历up的下级对象
for (Tree ts : collect) {
List<Tree> lower = getLower(ts, data);
ts.setChildren(lower);
}
return collect;
}
/**
* 根据分类id获取所有下级分类id(包括自己)
*
* @param id
* @param data
* @return
*/
public static Set<Integer> getLowerIds(Integer id, List<Tree> data) {
Set<Integer> ids = new LinkedHashSet<>();
ids.add(id);
ids.addAll(getLowerIds(ids, data));
return ids;
}
/**
* 根据分类id获取所有下级分类id(包括自己)
*
* @param ids
* @param data
* @return
*/
private static Set<Integer> getLowerIds(Set<Integer> ids, List<Tree> data) {
if (ids == null || ids.size() == 0) {
return ids;
}
// 下级id集合
Set<Integer> lowerIds = data.stream().filter(d -> ids.contains(d.getParentId())).map(Tree::getId)
.collect(Collectors.toSet());
lowerIds.addAll(getLowerIds(lowerIds, data));
return lowerIds;
}
}
递归对象
import com.fasterxml.jackson.annotation.JsonInclude;
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.stream.Collectors;
/**
* tree树结构实体类
*
* @author ljp
*/
public class Tree implements Serializable {
private static final long serialVersionUID = 1L;
/** 节点ID */
private Integer id;
/** 节点名称 */
private String label;
/** 所属层级 */
private Integer level;
/** 父节点 */
private Integer parentId;
/** 子节点 */
@JsonInclude(JsonInclude.Include.NON_EMPTY)
private List<Tree> children;
public Tree() {
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getLabel() {
return label;
}
public void setLabel(String label) {
this.label = label;
}
public Integer getLevel() {
return level;
}
public void setLevel(Integer level) {
this.level = level;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public List<Tree> getChildren() {
return children;
}
public void setChildren(List<Tree> children) {
this.children = children;
}
}
使用示例
TreeSelectUtil.change(list().stream().map(Tree::new).collect(Collectors.toList()));
这里的list()是需要递归的数据集合(例:List<WareClass>) map(Tree:new) 是 map(wareClass->new Tree(wareClass))
的简写
调用的是tree的构造方法
构造方法可参考
public Tree(WareClass ware) {
this.id = ware.getId();
this.label = ware.getClassName();
this.level = ware.getLevel();
this.parentId = ware.getSuperClassId();
this.children = ware.getChildren() == null ? Collections.emptyList()
: ware.getChildren().stream().map(Tree::new).collect(Collectors.toList());
}
说明
编写思路
如图:将数据1+data得到集合作为递归方法循环调用
漏洞修复
// 先取出最上级
//这里判断上级id为空或为-1时时最上级
//部分数据递归时会有漏洞,下面会修复
List list = data.stream().filter(d -> d.getParentId() == null || d.getParentId() == -1)
.collect(Collectors.toList());
这里的最上级判断是上级id为空的数据,如果只需递归第二级别以下的数据(例如只有第二级的权限)
就不能实现了,这里需要修改为
//获取最上级
int level = data.stream().mapToInt(Tree::getLevel).min().getAsInt();
//从最上级开始递归
List<Tree> list = data.stream().filter(d -> d.getLevel().equals(level))
.collect(Collectors.toList());
注意,这里的层级是必填的,且是正确的数据
扩展-根据ID集合获取名称(自动取上级)
/**
* 自动获取上级
* @param selectIds
* @return
*/
public String getName(List<Long> selectIds){
//所有数据
List<Tree> data=list();
List<Map<Long, List<Long>>> levels = new ArrayList<>();
while (true) {
//层级
int level = levels.size() + 1;
Map<Long, List<Long>> map = new HashMap<>();
//层级对应的id集合
List<Long> levelIds = data.stream()
.filter(d -> d.getLevel().equals(level))
.map(Tree::getId).collect(Collectors.toList());
if (levelIds.isEmpty()) {
break;
}
//上级id和下级id集合映射
for (Long id : levelIds) {
map.put(id, data.stream().filter(d -> id.equals(d.getParentId()))
.map(Tree::getId).collect(Collectors.toList()));
}
levels.add(map);
}
//拥有所有下级自动转上级
for (int i = levels.size() - 1; i > -1; i--) {
for (Map.Entry<Long, List<Long>> entry : levels.get(i).entrySet()) {
if (entry.getValue().size() > 0) {
if (ids.containsAll(entry.getValue())) {
//删除下级
ids.removeAll(entry.getValue());
//添加上级
ids.add(entry.getKey());
}else if(!isAllNotContains(ids,entry.getValue())){
//只包含部分则删除上级
ids.remove(entry.getKey());
}
}
}
}
//返回用逗号隔开的最终结果(排序)
return data.stream().filter(d->ids.contains(d.getId()))
.sorted(new Comparator<Tree>() {
@Override
public int compare(Tree o1, Tree o2) {
return o1.getLevel()-o2.getLevel();
}
}).map(Tree::getLabel).collect(Collectors.joining(","));
}
/**
* 是否全部不包含
* @param ids
* @param values
* @return
*/
private boolean isAllNotContains(List<Long> ids,List<Long> values){
for(Long id : ids){
if(values.contains(id)){
return false;
}
}
return true;
}