我们在开发中难免会遇到在树形结构化数据中模糊查找某个字段,这种查询并不适合在数据库中做,最好是控制在代码层级。并且在树形结构化数据查找中,一般都会满足以下几个条件:
1. 如果当前搜索值存在,那么不管子集存不存在,当前数据都需要查出来
2. 如果当前搜索值不存在,同时他的子集存在,那么当前包含子集的数据都需要查出来
3. 如果当前搜索值不存在,并且子集也不存在,那么当前数据需要移除掉
package com.ican.kqyz.system.utils;
import com.alibaba.fastjson.JSON;
import org.springframework.util.CollectionUtils;
import java.util.ArrayList;
import java.util.List;
/**
* @Description: 子集处理类
* @Title: ChildHandle
* @Package com.ican.kqyz.system.utils
* @Author: zangdy
* @CreateTime: 2022/10/20 10:06
*/
public class ChildHandle {
/** id */
private Integer id;
/** 父级id */
private Integer parentId;
/** 名称 */
private String name;
/** 子集 */
private List<ChildHandle> child;
public static void main(String[] args) {
// 模拟数据
List<ChildHandle> list = mockData();
// 获取层级关系
list = getChild(0, list);
System.out.println(JSON.toJSONString(list));
// 搜索树形结构数据
list = childSearchName(list,"测试011");
System.out.println(JSON.toJSONString(list));
}
/**
* 搜索树形结构数据
* 1. 如果当前搜索值存在,那么不管子集存不存在,当前数据都需要查出来
* 2. 如果当前搜索值不存在,同时他的子集存在,那么当前包含子集的数据都需要查出来
* 3. 如果当前搜索值不存在,并且子集也不存在,那么当前数据需要移除掉
* @param list
* @param search
* @return
*/
private static List<ChildHandle> childSearchName(List<ChildHandle> list, String search) {
if (CollectionUtils.isEmpty(list)){
return null;
}
// 默认当前搜索含有该值
for (int i = 0; i < list.size(); i++) {
ChildHandle item = list.get(i);
if(item.getName().contains(search)) {
// 当前搜索含有该值
childSearch(item.getChild(), search, true);
}else {
// 当前搜索不含有该值
boolean flag = childSearch(item.getChild(), search, false);
// 下级没有搜索到
if(!flag){
// 移除
list.remove(i);
i--;
}
}
}
return list;
}
/**
* 递归搜索值操作
* @param list
* @param search
* @param flag
* @return
*/
private static boolean childSearch(List<ChildHandle> list, String search, boolean flag) {
if(flag){
// 如果父级存在,子集不需要判断了
return true;
}
if(CollectionUtils.isEmpty(list)){
return flag;
}
// 本次搜索默认不存在
boolean newFlag = false;
for (int i = 0; i < list.size(); i++) {
// 当前搜索值是否存在
boolean thisSearchFlag;
ChildHandle item = list.get(i);
if(item.getName().contains(search)) {
// 当前搜索值存在
thisSearchFlag = childSearch(item.getChild(), search, true);
}else {
// 当前搜索值不存在
thisSearchFlag = childSearch(item.getChild(), search, flag);
// 下级没有搜索到
if(!thisSearchFlag){
// 移除
list.remove(i);
i--;
}
}
// 如果上一级不存在则跟随当前搜索结果
if(thisSearchFlag){
newFlag = true;
}
}
// 如果上次搜索不存在则用当前搜索结果
if(!flag){
flag = newFlag;
}
return flag;
}
/**
* 获取子集
*
* @param parentId
* @param list
* @return
*/
public static List<ChildHandle> getChild(Integer parentId, List<ChildHandle> list) {
if (CollectionUtils.isEmpty(list) || parentId == null) {
return null;
}
// 组装新的树形结构数据
List<ChildHandle> newList = new ArrayList<>();
for (ChildHandle child : list) {
// 如果父级内码是当前内码,就继续
if (parentId.equals(child.getParentId())) {
// 寻找下级
child.setChild(getChild(child.getId(), list));
newList.add(child);
}
}
return newList;
}
/**
* 模拟数据
* @return
*/
private static List<ChildHandle> mockData() {
List<ChildHandle> list = new ArrayList<>();
ChildHandle ch1 = new ChildHandle();
ch1.setId(1);
ch1.setParentId(0);
ch1.setName("测试000");
list.add(ch1);
ChildHandle ch2 = new ChildHandle();
ch2.setId(2);
ch2.setParentId(0);
ch2.setName("测试011");
list.add(ch2);
ChildHandle ch3 = new ChildHandle();
ch3.setId(3);
ch3.setParentId(2);
ch3.setName("测试333");
list.add(ch3);
ChildHandle ch4 = new ChildHandle();
ch4.setId(4);
ch4.setParentId(1);
ch4.setName("测试020");
list.add(ch4);
ChildHandle ch5 = new ChildHandle();
ch5.setId(5);
ch5.setParentId(1);
ch5.setName("测试030");
list.add(ch5);
ChildHandle ch6 = new ChildHandle();
ch6.setId(6);
ch6.setParentId(4);
ch6.setName("测试20");
list.add(ch6);
ChildHandle ch7 = new ChildHandle();
ch7.setId(7);
ch7.setParentId(6);
ch7.setName("测试203");
list.add(ch7);
return list;
}
public Integer getParentId() {
return parentId;
}
public void setParentId(Integer parentId) {
this.parentId = parentId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<ChildHandle> getChild() {
return child;
}
public void setChild(List<ChildHandle> child) {
this.child = child;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
}