热门标签 | HotTags
当前位置:  开发笔记 > 开发工具 > 正文

list转tree和list中查找某节点下的所有数据操作

这篇文章主要介绍了list转tree和list中查找某节点下的所有数据操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

类的实例化顺序

父类静态变量、 父类静态代码块、 子类静态变量、 子类静态代码块、

父类非静态变量(父类实例成员变量)、 父类构造函数、 子类非静态变量(子类实例成员变量)、 子类构造函数。

已知组织类Org{String id,String name,String parentId},现在一List中存放无序的Org数据,求一个组织id下的所有组织。

public static List childList=new ArrayList<>(); 
public static List findChild(List list,String id){
   for (Org org:list){
    if(org.getParentId().equals(id)){
     childList.add(org);
     findChild(list,org.getId()); //递归实现
 
    }
  }
  return childList;
  }

list转tree:

 // node一开始为根节点
 public static TreeNode listToTree(TreeNode node, List sourceLit){
  // 重根节点开始
  for (TreeNode sourceNode : sourceLit){
   if (sourceNode.getpId() == node.getId()){
     if(node.getChildrenList() == null){
      node.setChildrenList(new ArrayList());
     }
     node.getChildrenList().add(listToTree(sourceNode, sourceLit));
   }
  }
  return node;
 }

补充知识:Java实现树数据Tree与List互转并逐级汇总节点的值(支持树节点多列统计)

主要需求:a.实现树Tree与List互转 b.Tree实现多列统计数据汇总。前度采用MiniUI。

逐级汇总数据:找到最小节点,然后回溯其所有父节点,注意值的重复计算问题。

构造一棵树的基本节点:

package com.example.demo.tree; 
import java.util.ArrayList;
import java.util.List;
 
/**
 * @ClassName: TreeNode
 * @Description: TODO(树的节点对象)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-06-18 23:35
 */
public class TreeNode {
 
 /**
  * 节点ID
  */
 private long id;
 /**
  * 显示名称
  */
 private String label;
 /**
  * 当前节点的唯一值
  */
 private double value;
 /**
  * 当前节点的多个值的表达方式
  */
 private double[] multiValues=new double[]{};
 /**
  * 汇总单个节点的多个值
  */
 private List values=new ArrayList();
 /**
  * 当前节点所有子节点的值集合
  */
 private List childrenMultiValues=new ArrayList();
 /**
  * 父节点ID
  */
 private long pid;
 /**
  * 子节点集合对象
  */
 private List children=new ArrayList();
 /**
  * 是否计算本身
  */
 private boolean addSelf=false;
 
 public long getId() {
  return id;
 }
 
 public void setId(long id) {
  this.id = id;
 }
 
 public String getLabel() {
  return label;
 }
 
 public void setLabel(String label) {
  this.label = label;
 }
 
 public double getValue() {
  return value;
 }
 
 public void setValue(double value) {
  this.value = value;
 }
 
 public double[] getMultiValues() {
  return multiValues;
 }
 
 public void setMultiValues(double[] multiValues) {
  this.multiValues = multiValues;
 }
 
 public List getValues() {
  return values;
 }
 
 public void setValues(List values) {
  this.values = values;
 }
 
 public List getChildrenMultiValues() {
  return childrenMultiValues;
 }
 
 public void setChildrenMultiValues(List childrenMultiValues) {
  this.childrenMultiValues = childrenMultiValues;
 }
 
 public long getPid() {
  return pid;
 }
 
 public void setPid(long pid) {
  this.pid = pid;
 }
 
 public List getChildren() {
  return children;
 }
 
 public void setChildren(List children) {
  this.children = children;
 }
 
 public boolean isAddSelf() {
  return addSelf;
 }
 
 public void setAddSelf(boolean addSelf) {
  this.addSelf = addSelf;
 }
}

构造树管理工具:

package com.example.demo.tree; 
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
 * @ClassName: TreeManager
 * @Description: TODO(树结构数据管理-实践验证)
 * @author: pengjunlin
 * @motto: 学习需要毅力,那就秀毅力
 * @date 2019-06-18 23:47
 */
public class TreeManager {
 
 /**
  * 将List转成tree结构数据
  * @param list
  * @param rootId 默认顶级节点ID
  * @return
  */
 public static List listToTree(List list,long rootId){
  List tree=new ArrayList();
  Map map = new HashMap();
  // 将所有的数据,以键值对的形式装入map中
  for (TreeNode node : list) {
   // 去除冗余的子节点
   node.setChildren(new ArrayList());
   map.put(node.getId(), node);
  }
  for (TreeNode node : list) {
   // 如果id是父级的话就放入tree中
   if (node.getId() == rootId) {
    tree.add(node);
   } else {
    // 子级通过父id获取到父级的类型
    TreeNode parent = map.get(node.getPid());
    // 父级获得子级,再将子级放到对应的父级中
    if(parent!=null){
     parent.getChildren().add(node);
    }
   }
  }
  return tree;
 }
 
 /**
  * 将tree结构数据转成List结构
  * @param list
  * @return
  */
 public static void treeToList(TreeNode node,List list){
  if(list==null){
   list=new ArrayList();
  }
  //设置当前节点的必要数据
  TreeNode nodeValue=new TreeNode();
  nodeValue.setId(node.getId());
  nodeValue.setLabel(node.getLabel());
  nodeValue.setValue(node.getValue());
  nodeValue.setMultiValues(node.getMultiValues());
  nodeValue.setChildrenMultiValues(node.getChildrenMultiValues());
  nodeValue.setPid(node.getPid());
  nodeValue.setChildren(new ArrayList());
  list.add(nodeValue);
  //遍历递归子节点
  if(node.getChildren().size()>0){
   for (int i = 0; i  listToTreeWithSingleValue(List list,long rootId){
  Map map = new HashMap();
  // 将所有的数据,以键值对的形式装入map中
  for (TreeNode node : list) {
   // 去除冗余的子节点
   node.setChildren(new ArrayList());
   map.put(node.getId(), node);
  }
  List tree=listToTree(list,rootId);
  /* // 存储最小子节点ID
  Map leafList=new HashMap();
  findMinNodes(tree.get(0),leafList,0);
  // 设置每个节点的值
  for (Long id_: leafList.keySet()) {
   // 内部递归树的父节点层级多于2会存在重复计算
   setParentNodeValue(map,id_);
  }*/
 
  // 存储最小子节点ID
  Map leaf=new HashMap();
  findMinNodes(tree.get(0),leaf);
  // 逐级设置父节点的值
  setValuesToParentNode(leaf, map);
 
  // 汇总所有节点的值
  double total=0;
  for (TreeNode node:map.values() ) {
   total=0;
   for (double value: node.getValues() ) {
    total+=value;
   }
   node.setValue(total);
   map.put(node.getId(),node);
  }
  List result=new ArrayList();
  for (TreeNode node:map.values()) {
   result.add(node);
  }
  return listToTree(result,rootId);
 }
 
 /**
  * 转换数据格式并设置对应节点的值汇总到根节点
  * @param tree
  * @return
  */
 public static List treeToListWithSingleValue(TreeNode tree){
  List list=new ArrayList();
  // 获取到List
  treeToList(tree,list);
  Map map = new HashMap();
  // 将所有的数据,以键值对的形式装入map中
  for (TreeNode node : list) {
   // 去除冗余的子节点
   node.setChildren(new ArrayList());
   map.put(node.getId(), node);
  }
  /* // 存储最小子节点ID
  Map leafList=new HashMap();
  findMinNodes(tree,leafList,0);
  // 设置每个节点的值
  for (Long id_: leafList.keySet()) {
   // 内部递归树的父节点层级多于2会存在重复计算
   setParentNodeValue(map,id_);
  }*/
 
  // 存储最小子节点ID
  Map leaf=new HashMap();
  findMinNodes(tree,leaf);
  // 逐级设置父节点的值
  setValuesToParentNode(leaf, map);
 
  // 汇总所有节点的值
  double total=0;
  for (TreeNode node:map.values() ) {
   total=0;
   for (double value: node.getValues() ) {
    total+=value;
   }
   node.setValue(total);
   map.put(node.getId(),node);
  }
  List result=new ArrayList();
  for (TreeNode node:map.values()) {
   result.add(node);
  }
  return result;
 }
 
 /**
  * 转换数据格式并设置对应节点的值汇总到根节点
  * @param list
  * @param rootId
  * @param columns
  * @return
  */
 public static List listToTreeWithMultiValues(List list,long rootId,int columns){
  Map map = new HashMap();
  // 将所有的数据,以键值对的形式装入map中
  for (TreeNode node : list) {
   // 去除冗余的子节点
   node.setChildren(new ArrayList());
   map.put(node.getId(), node);
  }
  List tree=listToTree(list,rootId);
 
  /* // 存储最小子节点ID
  Map leafList=new HashMap();
  findMinNodes(tree.get(0),leafList,0);
  // 设置每个节点的值
  for (Long id_: leafList.keySet()) {
   // 内部递归树的父节点层级多于2会存在重复计算
   setParentNodeMultiValues(map,id_);
  }*/
 
  // 存储最小子节点ID
  Map leaf=new HashMap();
  findMinNodes(tree.get(0),leaf);
  // 逐级追加父节点的值
  setMultiValuesToParentNode(leaf, map);
 
  // 汇总所有节点的值
  double [] valueColumns=null;
  for (TreeNode node:map.values() ) {
   valueColumns=new double[columns];
   for (double [] values: node.getChildrenMultiValues() ) {
    for (int i = 0,j=values.length; i  result=new ArrayList();
  for (TreeNode node:map.values()) {
   result.add(node);
  }
  return listToTree(result,rootId);
 }
 
 /**
  * 转换数据格式并设置对应节点的值汇总到根节点
  * @param tree
  * @param columns
  * @return
  */
 public static List treeToListWithMultiValues(TreeNode tree,int columns){
  List list=new ArrayList();
  // 获取到List
  treeToList(tree,list);
  Map map = new HashMap();
  // 将所有的数据,以键值对的形式装入map中
  for (TreeNode node : list) {
   // 去除冗余的子节点
   node.setChildren(new ArrayList());
   map.put(node.getId(), node);
  }
  /*
  // 存储最小子节点ID
  Map leafList=new HashMap();
  findMinNodes(tree,leafList,0);
  // 设置每个节点的值
  for (Long id_: leafList.keySet()) {
    // 内部递归树的父节点层级多于2会存在重复计算
   setParentNodeMultiValues(map,id_);
  }*/
 
  // 存储最小子节点ID
  Map leaf=new HashMap();
  findMinNodes(tree,leaf);
  // 逐级追加父节点的值
  setMultiValuesToParentNode(leaf, map);
 
  // 汇总所有节点的值
  double [] valueColumns=null;
  for (TreeNode node:map.values() ) {
   valueColumns=new double[columns];
   for (double [] values: node.getChildrenMultiValues() ) {
    for (int i = 0,j=values.length; i  result=new ArrayList();
  for (TreeNode node:map.values()) {
   result.add(node);
  }
  return result;
 }
 
 /**
  * 逐级追加设置节点的值(单个值)
  * @param leaf
  * @param map
  */
 public static void setValuesToParentNode(Map leaf,Map map){
  Map newLeaf=new HashMap();
  // 设置每个节点的值
  for (Long id_: leaf.keySet()) {
   setParentNodeValue(newLeaf,map,id_);
  }
  if(newLeaf.size()>1){
   setValuesToParentNode(newLeaf, map);
  }
 }
 
 /**
  * 逐级追加设置节点的值(多个值)
  * @param leaf
  * @param map
  */
 public static void setMultiValuesToParentNode( Map leaf,Map map){
  Map newLeaf=new HashMap();
  // 设置每个节点的值
  for (Long id_: leaf.keySet()) {
   setParentNodeMultiValues(newLeaf,map,id_);
  }
  if(newLeaf.size()>1){
   setMultiValuesToParentNode(newLeaf, map);
  }
 }
 
 /**
  * 数学运算
  * @param mathChar
  * @param dest
  * @param newValue
  */
 public static void mathHandle(String mathChar,double dest,double newValue){
  switch (mathChar) {
   case "+":
    dest+=newValue;
    break;
   case "-":
    dest-=newValue;
    break;
   case "*":
    dest*=newValue;
    break;
   case "/":
    dest/=newValue;
    break;
   default:
    break;
  }
 }
 
 /**
  * 查找最小子叶节点(没有子节点的节点)
  * @param node
  * @param leafList
  */
 private static void findMinNodes(TreeNode node,Map leafList){
  if(node.getChildren().size()>0){
   TreeNode nodeTmp=null;
   for (int i = 0; i  newLeaf,Map map,long id){
  TreeNode node=map.get(id);
  // 设置自身节点的值
  if(!node.isAddSelf()){
   node.setAddSelf(true);
   node.getValues().add(node.getValue());
   // 更新节点数据
   map.put(node.getId(),node);
  }
  TreeNode pNode=map.get(node.getPid());
  if(pNode!=null){
   // 将子节点的值赋给父节点
   pNode.getValues().addAll(node.getValues());
   // 设置自身节点的值
   if(!pNode.isAddSelf()){
    pNode.setAddSelf(true);
    pNode.getValues().add(pNode.getValue());
   }
   // 更新节点数据
   map.put(pNode.getId(),pNode);
   //setParentNodeValue(map,pNode.getId());
   newLeaf.put(pNode.getId(), pNode.getId());
  }
 }
 
 /**
  * 根据ID逐级查找父节点并设置值(设置多个值逐级递归)
  * @param map
  * @param id
  */
 private static void setParentNodeMultiValues(Map newLeaf,Map map,long id){
  TreeNode node=map.get(id);
  // 设置自身节点的值
  if(!node.isAddSelf()){
   node.setAddSelf(true);
   node.getChildrenMultiValues().add(node.getMultiValues());
   // 更新节点数据
   map.put(node.getId(),node);
  }
  TreeNode pNode=map.get(node.getPid());
  if(pNode!=null){
   // 将子节点的值赋给父节点
   pNode.getChildrenMultiValues().addAll(node.getChildrenMultiValues());
   // 设置自身节点的值
   if(!pNode.isAddSelf()){
    pNode.setAddSelf(true);
    pNode.getChildrenMultiValues().add(pNode.getMultiValues());
   }
   // 更新节点数据
   map.put(pNode.getId(),pNode);
   //setParentNodeMultiValues(map,pNode.getId());
   newLeaf.put(pNode.getId(), pNode.getId());
  }
 }
 
 @SuppressWarnings("unused")
 public static void main(String[] args) {
  TreeNode tree=new TreeNode();
  tree.setId(1);
  tree.setLabel("顶层节点");
  tree.setValue(1);
  tree.setChildrenMultiValues(new ArrayList());
  tree.setPid(0);
 
  List list =new ArrayList();
  TreeNode node1=new TreeNode();
  node1.setId(2);
  node1.setLabel("子节点1");
  node1.setValue(100);
  node1.setMultiValues(new double[]{5,7,3});
  node1.setChildrenMultiValues(new ArrayList());
  node1.setPid(1);
  list.add(node1);
  TreeNode node2=new TreeNode();
  node2.setId(3);
  node2.setLabel("子节点2");
  node2.setValue(10);
  node2.setMultiValues(new double[]{2,5,8});
  node2.setChildrenMultiValues(new ArrayList());
  node2.setPid(1);
  list.add(node2);
 
  tree.setChildren(list);
 
  List destList=new ArrayList();
  TreeManager.treeToList(tree,destList);
  System.out.println("tree转list完成");
 
  List treeList=TreeManager.listToTree(destList,1);
 
  System.out.println("List转tree完成");
 
  /*******************注意单个值计算结果会影响多个值计算结果**************/
 
  List treeListSingleValue=TreeManager.listToTreeWithSingleValue(destList,1);
  System.out.println("List转tree 汇总唯一值value完成");
 
  List treeListSingleValue2=TreeManager.treeToListWithSingleValue(tree);
  System.out.println("tree转List 汇总唯一值value完成");
 
//  List treeListMultiValues=TreeManager.listToTreeWithMultiValues(destList,1,3);
//  System.out.println("List转tree 汇总多个值values完成");
//
//  List treeListMultiValues2=TreeManager.treeToListWithMultiValues(tree,3);
//  System.out.println("tree转List 汇总多个值values完成");
 
 }
}

注:如果数据字段跟工具树的不一致可以使用Map转对象来实现。

Github源码:点击进入

以上这篇list转tree和list中查找某节点下的所有数据操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持。


推荐阅读
  • 本文介绍了UUID(通用唯一标识符)的概念及其在JavaScript中生成Java兼容UUID的代码实现与优化技巧。UUID是一个128位的唯一标识符,广泛应用于分布式系统中以确保唯一性。文章详细探讨了如何利用JavaScript生成符合Java标准的UUID,并提供了多种优化方法,以提高生成效率和兼容性。 ... [详细]
  • 在IIS上运行的WebApi应用程序在开发环境中能够正常进行文件的读写操作。然而,在尝试通过FTP访问实时服务器上的文件列表时,遇到了无法显示的问题,尽管服务器配置与开发环境相同。这可能涉及权限设置、FTP服务配置或网络连接等方面的问题。 ... [详细]
  • Redis哈希数据结构入门指南
    Redis的哈希数据结构与Java中的HashMap类似,采用数组加链表的方式实现。数组用于存储哈希值的位置,而链表则用于处理哈希冲突的情况。此外,Redis的哈希数据结构还支持高效的字段操作和内存优化,适用于多种应用场景,如缓存和会话管理。 ... [详细]
  • 深入解析 Linux 内核中的 signal.c 文件:从泛读到精析
    本文将对 Linux 内核中的 `signal.c` 文件进行深入解析,从泛读到精析,全面解读其核心功能与实现机制。通过详细分析代码,探讨信号处理的内部运作,帮助读者更好地理解 Linux 内核的信号处理机制。相关学习资料已整理在 GitHub 仓库:https://github.com/GreyZhang/little_bits_of_linux。 ... [详细]
  • ### 日期:2018年3月20日在使用Makefile进行编译时,遇到错误提示“make (e=2) — 系统无法找到指定文件”。该问题通常是由路径配置不正确或目标文件缺失引起的。建议检查Makefile中的路径设置,并确保所有依赖文件都已正确放置在指定目录中。此外,可以尝试清理缓存并重新生成Makefile,以排除潜在的环境问题。 ... [详细]
  • 在 Angular Google Maps 中实现图片嵌入信息窗口的功能,可以通过使用 `@agm/core` 库来实现。该库提供了丰富的 API 和组件,使得开发者可以轻松地在地图上的信息窗口中嵌入图片。本文将详细介绍如何配置和使用这些组件,以实现动态加载和显示图片的功能。此外,还将探讨一些常见的问题和解决方案,帮助开发者更好地集成这一功能。 ... [详细]
  • 在TypeScript中,我定义了一个名为 `Employee` 的接口,其中包含 `id` 和 `name` 属性。为了使这些属性可选为空,可以通过使用 `| null` 或 `| undefined` 来扩展其类型定义。例如,`id: number | null` 表示 `id` 可以是数字或空值。这种类型的灵活性在处理不确定的数据时非常有用,可以提高代码的健壮性和可维护性。 ... [详细]
  • Node.js 配置文件管理方法详解与最佳实践
    本文详细介绍了 Node.js 中配置文件管理的方法与最佳实践,涵盖常见的配置文件格式及其优缺点,并提供了多种实用技巧和示例代码,帮助开发者高效地管理和维护项目配置,具有较高的参考价值。 ... [详细]
  • 投融资周报 | Circle 达成 4 亿美元融资协议,唯一艺术平台 A 轮融资超千万美元 ... [详细]
  • 深入解析 Android TextView 中 getImeActionLabel() 方法的使用与代码示例 ... [详细]
  • K3Cloud 平台字符串解密技术详解与应用
    在 K3Cloud 平台中,配置文件内的敏感信息如密码会被加密处理。通过深入研究,我们发现可以通过 Kingdee.BOS.Api 提供的接口对这些加密字符串进行解密。本文详细介绍了这一解密技术的具体实现方法及其应用场景,为开发者提供了宝贵的参考和实践指导。此外,还探讨了该技术在数据安全和系统管理中的重要性,以及如何在实际项目中高效地应用这些技术,确保系统的稳定性和安全性。 ... [详细]
  • 提升开发技能的八大策略与方法
    许多前端开发人员和客户都在寻求具备创新和技术能力的专业人才,但往往由于缺乏足够的曝光度和声誉,这些人才难以被潜在客户发现。本文将介绍八种有效策略和方法,帮助开发者提升技能并增强市场竞争力。 ... [详细]
  • 在GitHub上克隆vue-element-admin项目时遇到依赖安装错误
    在 GitHub 上克隆 vue-element-admin 项目后,使用 `npm install` 安装依赖时遇到了未知的 Git 错误。具体错误信息为 `npm ERR! code 128`,提示命令执行失败。这可能是由于网络问题、Git 配置不正确或某些依赖包的仓库地址无效导致的。建议检查网络连接、更新 Git 版本并确保所有依赖项的 URL 正确无误。 ... [详细]
  • 在《Python编程基础》课程中,我们将深入探讨Python中的循环结构。通过详细解析for循环和while循环的语法与应用场景,帮助初学者掌握循环控制语句的核心概念和实际应用技巧。此外,还将介绍如何利用循环结构解决复杂问题,提高编程效率和代码可读性。 ... [详细]
  • 设计模式详解:模板方法模式的应用与实现
    模板方法模式是一种行为设计模式,通过定义一个操作中的算法骨架,将具体步骤的实现延迟到子类中。本文详细解析了模板方法模式的类图结构、实现方式以及挂钩机制,并结合实际案例进行了深入探讨。此外,文章还提供了丰富的参考资料,帮助读者更好地理解和应用这一设计模式。对于手机用户,建议横屏阅读以获得更佳的阅读体验。 ... [详细]
author-avatar
会满足cy
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有