list轉tree和list中查找某節(jié)點下的所有數(shù)據(jù)操作
類的實例化順序
父類靜態(tài)變量、 父類靜態(tài)代碼塊、 子類靜態(tài)變量、 子類靜態(tài)代碼塊、
父類非靜態(tài)變量(父類實例成員變量)、 父類構造函數(shù)、 子類非靜態(tài)變量(子類實例成員變量)、 子類構造函數(shù)。
已知組織類Org{String id,String name,String parentId},現(xiàn)在一List<Org>中存放無序的Org數(shù)據(jù),求一個組織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()); //遞歸實現(xiàn)
}
}
return childList;
}
list轉tree:
// node一開始為根節(jié)點
public static TreeNode listToTree(TreeNode node, List<TreeNode> sourceLit){
// 重根節(jié)點開始
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實現(xiàn)樹數(shù)據(jù)Tree與List互轉并逐級匯總節(jié)點的值(支持樹節(jié)點多列統(tǒng)計)
主要需求:a.實現(xiàn)樹Tree與List互轉 b.Tree實現(xiàn)多列統(tǒng)計數(shù)據(jù)匯總。前度采用MiniUI。
逐級匯總數(shù)據(jù):找到最小節(jié)點,然后回溯其所有父節(jié)點,注意值的重復計算問題。


構造一棵樹的基本節(jié)點:
package com.example.demo.tree;
import java.util.ArrayList;
import java.util.List;
/**
* @ClassName: TreeNode
* @Description: TODO(樹的節(jié)點對象)
* @author: pengjunlin
* @motto: 學習需要毅力,那就秀毅力
* @date 2019-06-18 23:35
*/
public class TreeNode {
/**
* 節(jié)點ID
*/
private long id;
/**
* 顯示名稱
*/
private String label;
/**
* 當前節(jié)點的唯一值
*/
private double value;
/**
* 當前節(jié)點的多個值的表達方式
*/
private double[] multiValues=new double[]{};
/**
* 匯總單個節(jié)點的多個值
*/
private List<Double> values=new ArrayList<Double>();
/**
* 當前節(jié)點所有子節(jié)點的值集合
*/
private List<double []> childrenMultiValues=new ArrayList<double []>();
/**
* 父節(jié)點ID
*/
private long pid;
/**
* 子節(jié)點集合對象
*/
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(樹結構數(shù)據(jù)管理-實踐驗證)
* @author: pengjunlin
* @motto: 學習需要毅力,那就秀毅力
* @date 2019-06-18 23:47
*/
public class TreeManager {
/**
* 將List轉成tree結構數(shù)據(jù)
* @param list
* @param rootId 默認頂級節(jié)點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>();
// 將所有的數(shù)據(jù),以鍵值對的形式裝入map中
for (TreeNode node : list) {
// 去除冗余的子節(jié)點
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結構數(shù)據(jù)轉成List結構
* @param list
* @return
*/
public static void treeToList(TreeNode node,List<TreeNode> list){
if(list==null){
list=new ArrayList<TreeNode>();
}
//設置當前節(jié)點的必要數(shù)據(jù)
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);
//遍歷遞歸子節(jié)點
if(node.getChildren().size()>0){
for (int i = 0; i < node.getChildren().size(); i++) {
TreeNode node_= node.getChildren().get(i);
treeToList(node_,list);
}
}
}
/**
* 轉換數(shù)據(jù)格式并設置對應節(jié)點的值匯總到根節(jié)點
* @param list
* @param rootId
* @return
*/
public static List<TreeNode> listToTreeWithSingleValue(List<TreeNode> list,long rootId){
Map<Long, TreeNode> map = new HashMap<Long, TreeNode>();
// 將所有的數(shù)據(jù),以鍵值對的形式裝入map中
for (TreeNode node : list) {
// 去除冗余的子節(jié)點
node.setChildren(new ArrayList<TreeNode>());
map.put(node.getId(), node);
}
List<TreeNode> tree=listToTree(list,rootId);
/* // 存儲最小子節(jié)點ID
Map<Long,Object> leafList=new HashMap<Long,Object>();
findMinNodes(tree.get(0),leafList,0);
// 設置每個節(jié)點的值
for (Long id_: leafList.keySet()) {
// 內(nèi)部遞歸樹的父節(jié)點層級多于2會存在重復計算
setParentNodeValue(map,id_);
}*/
// 存儲最小子節(jié)點ID
Map<Long,Object> leaf=new HashMap<Long,Object>();
findMinNodes(tree.get(0),leaf);
// 逐級設置父節(jié)點的值
setValuesToParentNode(leaf, map);
// 匯總所有節(jié)點的值
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);
}
/**
* 轉換數(shù)據(jù)格式并設置對應節(jié)點的值匯總到根節(jié)點
* @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>();
// 將所有的數(shù)據(jù),以鍵值對的形式裝入map中
for (TreeNode node : list) {
// 去除冗余的子節(jié)點
node.setChildren(new ArrayList<TreeNode>());
map.put(node.getId(), node);
}
/* // 存儲最小子節(jié)點ID
Map<Long,Object> leafList=new HashMap<Long,Object>();
findMinNodes(tree,leafList,0);
// 設置每個節(jié)點的值
for (Long id_: leafList.keySet()) {
// 內(nèi)部遞歸樹的父節(jié)點層級多于2會存在重復計算
setParentNodeValue(map,id_);
}*/
// 存儲最小子節(jié)點ID
Map<Long,Object> leaf=new HashMap<Long,Object>();
findMinNodes(tree,leaf);
// 逐級設置父節(jié)點的值
setValuesToParentNode(leaf, map);
// 匯總所有節(jié)點的值
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;
}
/**
* 轉換數(shù)據(jù)格式并設置對應節(jié)點的值匯總到根節(jié)點
* @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>();
// 將所有的數(shù)據(jù),以鍵值對的形式裝入map中
for (TreeNode node : list) {
// 去除冗余的子節(jié)點
node.setChildren(new ArrayList<TreeNode>());
map.put(node.getId(), node);
}
List<TreeNode> tree=listToTree(list,rootId);
/* // 存儲最小子節(jié)點ID
Map<Long,Object> leafList=new HashMap<Long,Object>();
findMinNodes(tree.get(0),leafList,0);
// 設置每個節(jié)點的值
for (Long id_: leafList.keySet()) {
// 內(nèi)部遞歸樹的父節(jié)點層級多于2會存在重復計算
setParentNodeMultiValues(map,id_);
}*/
// 存儲最小子節(jié)點ID
Map<Long,Object> leaf=new HashMap<Long,Object>();
findMinNodes(tree.get(0),leaf);
// 逐級追加父節(jié)點的值
setMultiValuesToParentNode(leaf, map);
// 匯總所有節(jié)點的值
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);
}
/**
* 轉換數(shù)據(jù)格式并設置對應節(jié)點的值匯總到根節(jié)點
* @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>();
// 將所有的數(shù)據(jù),以鍵值對的形式裝入map中
for (TreeNode node : list) {
// 去除冗余的子節(jié)點
node.setChildren(new ArrayList<TreeNode>());
map.put(node.getId(), node);
}
/*
// 存儲最小子節(jié)點ID
Map<Long,Object> leafList=new HashMap<Long,Object>();
findMinNodes(tree,leafList,0);
// 設置每個節(jié)點的值
for (Long id_: leafList.keySet()) {
// 內(nèi)部遞歸樹的父節(jié)點層級多于2會存在重復計算
setParentNodeMultiValues(map,id_);
}*/
// 存儲最小子節(jié)點ID
Map<Long,Object> leaf=new HashMap<Long,Object>();
findMinNodes(tree,leaf);
// 逐級追加父節(jié)點的值
setMultiValuesToParentNode(leaf, map);
// 匯總所有節(jié)點的值
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;
}
/**
* 逐級追加設置節(jié)點的值(單個值)
* @param leaf
* @param map
*/
public static void setValuesToParentNode(Map<Long,Object> leaf,Map<Long, TreeNode> map){
Map<Long,Object> newLeaf=new HashMap<Long,Object>();
// 設置每個節(jié)點的值
for (Long id_: leaf.keySet()) {
setParentNodeValue(newLeaf,map,id_);
}
if(newLeaf.size()>1){
setValuesToParentNode(newLeaf, map);
}
}
/**
* 逐級追加設置節(jié)點的值(多個值)
* @param leaf
* @param map
*/
public static void setMultiValuesToParentNode( Map<Long,Object> leaf,Map<Long, TreeNode> map){
Map<Long,Object> newLeaf=new HashMap<Long,Object>();
// 設置每個節(jié)點的值
for (Long id_: leaf.keySet()) {
setParentNodeMultiValues(newLeaf,map,id_);
}
if(newLeaf.size()>1){
setMultiValuesToParentNode(newLeaf, map);
}
}
/**
* 數(shù)學運算
* @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;
}
}
/**
* 查找最小子葉節(jié)點(沒有子節(jié)點的節(jié)點)
* @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());
}
}
/**
* 根據(jù)ID逐級查找父節(jié)點并設置值(設置單個值逐級遞歸)
* @param map
* @param id
*/
private static void setParentNodeValue(Map<Long,Object> newLeaf,Map<Long, TreeNode> map,long id){
TreeNode node=map.get(id);
// 設置自身節(jié)點的值
if(!node.isAddSelf()){
node.setAddSelf(true);
node.getValues().add(node.getValue());
// 更新節(jié)點數(shù)據(jù)
map.put(node.getId(),node);
}
TreeNode pNode=map.get(node.getPid());
if(pNode!=null){
// 將子節(jié)點的值賦給父節(jié)點
pNode.getValues().addAll(node.getValues());
// 設置自身節(jié)點的值
if(!pNode.isAddSelf()){
pNode.setAddSelf(true);
pNode.getValues().add(pNode.getValue());
}
// 更新節(jié)點數(shù)據(jù)
map.put(pNode.getId(),pNode);
//setParentNodeValue(map,pNode.getId());
newLeaf.put(pNode.getId(), pNode.getId());
}
}
/**
* 根據(jù)ID逐級查找父節(jié)點并設置值(設置多個值逐級遞歸)
* @param map
* @param id
*/
private static void setParentNodeMultiValues(Map<Long,Object> newLeaf,Map<Long, TreeNode> map,long id){
TreeNode node=map.get(id);
// 設置自身節(jié)點的值
if(!node.isAddSelf()){
node.setAddSelf(true);
node.getChildrenMultiValues().add(node.getMultiValues());
// 更新節(jié)點數(shù)據(jù)
map.put(node.getId(),node);
}
TreeNode pNode=map.get(node.getPid());
if(pNode!=null){
// 將子節(jié)點的值賦給父節(jié)點
pNode.getChildrenMultiValues().addAll(node.getChildrenMultiValues());
// 設置自身節(jié)點的值
if(!pNode.isAddSelf()){
pNode.setAddSelf(true);
pNode.getChildrenMultiValues().add(pNode.getMultiValues());
}
// 更新節(jié)點數(shù)據(jù)
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("頂層節(jié)點");
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("子節(jié)點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("子節(jié)點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完成");
}
}
注:如果數(shù)據(jù)字段跟工具樹的不一致可以使用Map轉對象來實現(xiàn)。
Github源碼:點擊進入
以上這篇list轉tree和list中查找某節(jié)點下的所有數(shù)據(jù)操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
mybatis-plus?實現(xiàn)查詢表名動態(tài)修改的示例代碼
通過MyBatis-Plus實現(xiàn)表名的動態(tài)替換,根據(jù)配置或入?yún)⑦x擇不同的表,本文主要介紹了mybatis-plus?實現(xiàn)查詢表名動態(tài)修改的示例代碼,具有一定的參考價值,感興趣的可以了解一下2025-03-03
Java實現(xiàn)動態(tài)創(chuàng)建類操作示例
這篇文章主要介紹了Java實現(xiàn)動態(tài)創(chuàng)建類操作,結合完整示例形式分析了Java動態(tài)創(chuàng)建類的具體步驟與相關操作技巧,需要的朋友可以參考下2020-02-02
Spring Boot整合Mybatis Plus和Swagger2的教程詳解
這篇文章主要介紹了Spring Boot整合Mybatis Plus和Swagger2的教程,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-02-02
Java程序的初始化順序,static{}靜態(tài)代碼塊和實例語句塊的使用方式
這篇文章主要介紹了Java程序的初始化順序,static{}靜態(tài)代碼塊和實例語句塊的使用方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-01-01
說說@ModelAttribute在父類和子類中的執(zhí)行順序
這篇文章主要介紹了@ModelAttribute在父類和子類中的執(zhí)行順序,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-06-06

