类的实例化顺序 父类静态变量、 父类静态代码块、 子类静态变量、 子类静态代码块、 父类非静态变量(父类实例成员变量)、 父类构造函数、 子类非静态变量(子类实例成员变量)
类的实例化顺序
父类静态变量、 父类静态代码块、 子类静态变量、 子类静态代码块、
父类非静态变量(父类实例成员变量)、 父类构造函数、 子类非静态变量(子类实例成员变量)、 子类构造函数。
已知组织类Org{String id,String name,String parentId},现在一List<Org>中存放无序的Org数据,求一个组织id下的所有组织。
public static List<Org> childList=new ArrayList<>(); public static List<Org> findChild(List<Org> 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<TreeNode> sourceLit){ // 重根节点开始 for (TreeNode sourceNode : sourceLit){ if (sourceNode.getpId() == node.getId()){ if(node.getChildrenList() == null){ node.setChildrenList(new ArrayList<TreeNode>()); } 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<Double> values=new ArrayList<Double>(); /** * 当前节点所有子节点的值集合 */ private List<double []> childrenMultiValues=new ArrayList<double []>(); /** * 父节点ID */ private long pid; /** * 子节点集合对象 */ private List<TreeNode> children=new ArrayList<TreeNode>(); /** * 是否计算本身 */ 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<Double> getValues() { return values; } public void setValues(List<Double> values) { this.values = values; } public List<double[]> getChildrenMultiValues() { return childrenMultiValues; } public void setChildrenMultiValues(List<double[]> childrenMultiValues) { this.childrenMultiValues = childrenMultiValues; } public long getPid() { return pid; } public void setPid(long pid) { this.pid = pid; } public List<TreeNode> getChildren() { return children; } public void setChildren(List<TreeNode> 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<TreeNode> listToTree(List<TreeNode> list,long rootId){ List<TreeNode> tree=new ArrayList<TreeNode>(); Map<Long, TreeNode> map = new HashMap<Long, TreeNode>(); // 将所有的数据,以键值对的形式装入map中 for (TreeNode node : list) { // 去除冗余的子节点 node.setChildren(new ArrayList<TreeNode>()); 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<TreeNode> list){ if(list==null){ list=new ArrayList<TreeNode>(); } //设置当前节点的必要数据 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<TreeNode>()); list.add(nodeValue); //遍历递归子节点 if(node.getChildren().size()>0){ for (int i = 0; i < node.getChildren().size(); i++) { TreeNode node_= node.getChildren().get(i); treeToList(node_,list); } } } /** * 转换数据格式并设置对应节点的值汇总到根节点 * @param list * @param rootId * @return */ public static List<TreeNode> listToTreeWithSingleValue(List<TreeNode> list,long rootId){ Map<Long, TreeNode> map = new HashMap<Long, TreeNode>(); // 将所有的数据,以键值对的形式装入map中 for (TreeNode node : list) { // 去除冗余的子节点 node.setChildren(new ArrayList<TreeNode>()); map.put(node.getId(), node); } List<TreeNode> tree=listToTree(list,rootId); /* // 存储最小子节点ID Map<Long,Object> leafList=new HashMap<Long,Object>(); findMinNodes(tree.get(0),leafList,0); // 设置每个节点的值 for (Long id_: leafList.keySet()) { // 内部递归树的父节点层级多于2会存在重复计算 setParentNodeValue(map,id_); }*/ // 存储最小子节点ID Map<Long,Object> leaf=new HashMap<Long,Object>(); 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<TreeNode> result=new ArrayList<TreeNode>(); for (TreeNode node:map.values()) { result.add(node); } return listToTree(result,rootId); } /** * 转换数据格式并设置对应节点的值汇总到根节点 * @param tree * @return */ public static List<TreeNode> treeToListWithSingleValue(TreeNode tree){ List<TreeNode> list=new ArrayList<TreeNode>(); // 获取到List treeToList(tree,list); Map<Long, TreeNode> map = new HashMap<Long, TreeNode>(); // 将所有的数据,以键值对的形式装入map中 for (TreeNode node : list) { // 去除冗余的子节点 node.setChildren(new ArrayList<TreeNode>()); map.put(node.getId(), node); } /* // 存储最小子节点ID Map<Long,Object> leafList=new HashMap<Long,Object>(); findMinNodes(tree,leafList,0); // 设置每个节点的值 for (Long id_: leafList.keySet()) { // 内部递归树的父节点层级多于2会存在重复计算 setParentNodeValue(map,id_); }*/ // 存储最小子节点ID Map<Long,Object> leaf=new HashMap<Long,Object>(); 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<TreeNode> result=new ArrayList<TreeNode>(); for (TreeNode node:map.values()) { result.add(node); } return result; } /** * 转换数据格式并设置对应节点的值汇总到根节点 * @param list * @param rootId * @param columns * @return */ public static List<TreeNode> listToTreeWithMultiValues(List<TreeNode> list,long rootId,int columns){ Map<Long, TreeNode> map = new HashMap<Long, TreeNode>(); // 将所有的数据,以键值对的形式装入map中 for (TreeNode node : list) { // 去除冗余的子节点 node.setChildren(new ArrayList<TreeNode>()); map.put(node.getId(), node); } List<TreeNode> tree=listToTree(list,rootId); /* // 存储最小子节点ID Map<Long,Object> leafList=new HashMap<Long,Object>(); findMinNodes(tree.get(0),leafList,0); // 设置每个节点的值 for (Long id_: leafList.keySet()) { // 内部递归树的父节点层级多于2会存在重复计算 setParentNodeMultiValues(map,id_); }*/ // 存储最小子节点ID Map<Long,Object> leaf=new HashMap<Long,Object>(); 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 < j; i++) { valueColumns[i]+=values[i]; } } node.setMultiValues(valueColumns); map.put(node.getId(),node); } List<TreeNode> result=new ArrayList<TreeNode>(); for (TreeNode node:map.values()) { result.add(node); } return listToTree(result,rootId); } /** * 转换数据格式并设置对应节点的值汇总到根节点 * @param tree * @param columns * @return */ public static List<TreeNode> treeToListWithMultiValues(TreeNode tree,int columns){ List<TreeNode> list=new ArrayList<TreeNode>(); // 获取到List treeToList(tree,list); Map<Long, TreeNode> map = new HashMap<Long, TreeNode>(); // 将所有的数据,以键值对的形式装入map中 for (TreeNode node : list) { // 去除冗余的子节点 node.setChildren(new ArrayList<TreeNode>()); map.put(node.getId(), node); } /* // 存储最小子节点ID Map<Long,Object> leafList=new HashMap<Long,Object>(); findMinNodes(tree,leafList,0); // 设置每个节点的值 for (Long id_: leafList.keySet()) { // 内部递归树的父节点层级多于2会存在重复计算 setParentNodeMultiValues(map,id_); }*/ // 存储最小子节点ID Map<Long,Object> leaf=new HashMap<Long,Object>(); 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 < j; i++) { valueColumns[i]+=values[i]; } } node.setMultiValues(valueColumns); map.put(node.getId(),node); } List<TreeNode> result=new ArrayList<TreeNode>(); for (TreeNode node:map.values()) { result.add(node); } return result; } /** * 逐级追加设置节点的值(单个值) * @param leaf * @param map */ public static void setValuesToParentNode(Map<Long,Object> leaf,Map<Long, TreeNode> map){ Map<Long,Object> newLeaf=new HashMap<Long,Object>(); // 设置每个节点的值 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<Long,Object> leaf,Map<Long, TreeNode> map){ Map<Long,Object> newLeaf=new HashMap<Long,Object>(); // 设置每个节点的值 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<Long,Object> leafList){ if(node.getChildren().size()>0){ TreeNode nodeTmp=null; for (int i = 0; i < node.getChildren().size(); i++) { nodeTmp= node.getChildren().get(i); findMinNodes(nodeTmp,leafList); } }else{ leafList.put(node.getId(),node.getId()); } } /** * 根据ID逐级查找父节点并设置值(设置单个值逐级递归) * @param map * @param id */ private static void setParentNodeValue(Map<Long,Object> newLeaf,Map<Long, TreeNode> 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<Long,Object> newLeaf,Map<Long, TreeNode> 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<double []>()); tree.setPid(0); List<TreeNode> list =new ArrayList<TreeNode>(); TreeNode node1=new TreeNode(); node1.setId(2); node1.setLabel("子节点1"); node1.setValue(100); node1.setMultiValues(new double[]{5,7,3}); node1.setChildrenMultiValues(new ArrayList<double []>()); 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<double []>()); node2.setPid(1); list.add(node2); tree.setChildren(list); List<TreeNode> destList=new ArrayList<TreeNode>(); TreeManager.treeToList(tree,destList); System.out.println("tree转list完成"); List<TreeNode> treeList=TreeManager.listToTree(destList,1); System.out.println("List转tree完成"); /*******************注意单个值计算结果会影响多个值计算结果**************/ List<TreeNode> treeListSingleValue=TreeManager.listToTreeWithSingleValue(destList,1); System.out.println("List转tree 汇总唯一值value完成"); List<TreeNode> treeListSingleValue2=TreeManager.treeToListWithSingleValue(tree); System.out.println("tree转List 汇总唯一值value完成"); // List<TreeNode> treeListMultiValues=TreeManager.listToTreeWithMultiValues(destList,1,3); // System.out.println("List转tree 汇总多个值values完成"); // // List<TreeNode> treeListMultiValues2=TreeManager.treeToListWithMultiValues(tree,3); // System.out.println("tree转List 汇总多个值values完成"); } }
注:如果数据字段跟工具树的不一致可以使用Map转对象来实现。
Github源码:点击进入
以上这篇list转tree和list中查找某节点下的所有数据操作就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持易盾网络。