表结构
create table Project ( ID NUMBER not null, NAME VARCHAR2(50), PID NUMBER //父节点 )
实体
public class Project implements Serializable { private String Id; private String pId; private List<Project> childrenProjectList; }
从一级往下递归组树
以下是Sqlserver的递归sql,mysql的话可以对应去查,原理是一样的,就是用sql查出所有树节点,然后存入hashmap(以pid为key,list为value),然后从一级项目去map里取,如果不想用递归sql,如果数据不多可以直接查出所有数据放入hashmap,如果数据多可以在java代码里循环查询数据库找出所有的节点(不推荐,频繁查库)
查询符合条件的数据和子节点
with subqry(Id,projectname,pid) as ( select id,projectname,pid from Project where ProjectManager = 'gehui' union all select Project.id,Project.projectname,Project.pid from Project,subqry where Project.pid = subqry.id ) select * from subqry;
查询符合条件的数据和父节点
with maco as ( select * from Project where ProjectManager = 'gehui' union all select t.* from Project t,maco m where t.Id=m.pid ) select * from maco order by ProjectManager
获取树节点
projectSonList = projectMapper.selectSonProject(query); projectFatherList = projectMapper.selectFatherProject(query); projectFatherList.addAll(projectSonList); projectAllList = projectFatherList.stream().distinct().collect(Collectors.toList());
将节点放入hashmap
HashMap<String, List<Project>> ProjectMap= getProjectPidMap(projectAllList);
/** * 生成id为key的map * * @param projectFatherList * @return */ public HashMap<String, List<Project>> getProjectIdMap(List<Project> projectFatherList) { HashMap<String, List<Project>> allProjectIdMap = new HashMap<>(); //把所有的项目进行处理,用hashmap存储,以id为key,实体为value if (projectFatherList.size() != 0) { for (Project project : projectFatherList ) { // map中没有,并且不是父id不为空 if (project.getId() != null) { if (allProjectIdMap.get(project.getId()) == null) { List<Project> projectLists = new ArrayList<>(); projectLists.add(project); allProjectIdMap.put(project.getId(), projectLists); } else { allProjectIdMap.get(project.getId()).add(project); } } } } return allProjectIdMap; }
/** * 生成pid为key的map * * @param projectFatherList * @return */ public HashMap<String, List<Project>> getProjectPidMap(List<Project> projectFatherList) { HashMap<String, List<Project>> allProjectIdMap = new HashMap<>(); //把所有的项目进行处理,用hashmap存储,以id为key,实体为value if (projectFatherList.size() != 0) { for (Project project : projectFatherList ) { // map中没有,并且不是父id不为空 if (project.getpId() != null) { if (allProjectIdMap.get(project.getpId()) == null) { List<Project> projectLists = new ArrayList<>(); projectLists.add(project); allProjectIdMap.put(project.getpId(), projectLists); } else { allProjectIdMap.get(project.getpId()).add(project); } } } } return allProjectIdMap; }
开始组树
/** * 从一级向下递归 * * @param projectFatherList * @return */ public List<Project> getProjectTree(List<Project> projectFatherList, HashMap<String, List<Project>> allProjectMap) { //遍历,拿出所有的pidw为零的项目 List<Project> firstLeaveProject = projectFatherList.stream().filter(project -> StringUtils.isEmpty(project.getpId())).collect(Collectors.toList()); projectFatherList = getAllBottomProject(firstLeaveProject, allProjectMap); return projectFatherList; }
递归向下
/** * 递归遍历此项目下所有项目 * * @param leaveProjectList * @return */ public List<Project> getAllBottomProject(List<Project> leaveProjectList, HashMap<String, List<Project>> allProjectMap) { if (leaveProjectList != null && leaveProjectList.size() != 0 && !allProjectMap.isEmpty()) { for (int i = leaveProjectList.size() - 1; i >= 0; i--) { if (leaveProjectList.get(i).getId() != null && allProjectMap.get(leaveProjectList.get(i).getId()) != null) { leaveProjectList.get(i).setChildrenProjectList(allProjectMap.get(leaveProjectList.get(i).getId())); //递归调用,查看子集是否还有子集 getAllBottomProject(leaveProjectList.get(i).getChildrenProjectList(), allProjectMap); } } } return leaveProjectList; }
树形菜单的搜索
根据筛选条件递归向上建树
/** * 递归向上建树 * * @param leaveProjectList * @return */ public List<Project> getAllProject(List<Project> leaveProjectList, List<Project> projectAllList, List<Project> projectLeaveFatherList) throws IOException, ClassNotFoundException { if (leaveProjectList != null && leaveProjectList.size() != 0) { for (Project project : leaveProjectList ) { List<Project> projectTempList = new LinkedList<>(); List<Project> leaveProjectFatherList = new LinkedList<>(); List<Project> leaveEqualsProject = new LinkedList<>(); // 为每个元素找到父级树 leaveProjectFatherList = projectAllList.stream().filter(e -> e.getId().equals(project.getpId())).collect(Collectors.toList()); if (leaveProjectFatherList.size() > 0) { // 把该元素放到父级树的子集树元素集中 leaveProjectFatherList.get(0).setChildrenProjectList(leaveEqualsProject); leaveProjectFatherList.get(0).getChildrenProjectList().add(project); leaveProjectFatherList.get(0).setHigh(project.getHigh() + Constant.ONE); if (leaveProjectFatherList.get(0).getpId() != null) { leaveProjectFatherList = getProject(leaveProjectFatherList, projectAllList); } if (leaveProjectFatherList.get(0) != null && leaveProjectFatherList.get(0).getpId() == null) { projectLeaveFatherList.addAll(deepCopy(leaveProjectFatherList)); } } else { projectTempList.add(project); projectLeaveFatherList.addAll(deepCopy(projectTempList)); } } } return projectLeaveFatherList; } public static <T> List<T> deepCopy(List<T> src) throws IOException, ClassNotFoundException { ByteArrayOutputStream byteOut = new ByteArrayOutputStream(); ObjectOutputStream out = new ObjectOutputStream(byteOut); out.writeObject(src); ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray()); ObjectInputStream in = new ObjectInputStream(byteIn); @SuppressWarnings("unchecked") List<T> dest = (List<T>) in.readObject(); return dest; } public List<Project> getProject(List<Project> leaveProjectList, List<Project> projectAllList) { List<Project> leaveProjectFather; List<Project> leaveEquals = new LinkedList<>(); if (leaveProjectList != null && leaveProjectList.size() != 0) { for (Project project : leaveProjectList ) { // 为每个元素找到父级树 leaveProjectFather = projectAllList.stream().filter(e -> e.getId().equals(project.getpId())).collect(Collectors.toList()); if (leaveProjectFather.size() > 0) { // 把该元素放到父级树的子集树元素集中 leaveProjectFather.get(0).setChildrenProjectList(leaveEquals); leaveProjectFather.get(0).getChildrenProjectList().add(project); leaveProjectFather.get(0).setHigh(project.getHigh() + Constant.ONE); leaveProjectList = leaveProjectFather; leaveProjectList = getProject(leaveProjectList, projectAllList); } } } return leaveProjectList; }
总结
其实小编最喜欢的还是需要哪层返回哪层的数据,这样不需要递归,比如初始化只显示一级菜单,那么只返回一级菜单即可,点击再返回下一层