最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

java之TreeUtils生成一切對(duì)象樹形結(jié)構(gòu)案例

 更新時(shí)間:2020年09月23日 14:58:49   作者:不良人_  
這篇文章主要介紹了java之TreeUtils生成一切對(duì)象樹形結(jié)構(gòu)案例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧

項(xiàng)目中經(jīng)常會(huì)遇到各種需要以樹形結(jié)構(gòu)展示的功能,比較常見的,如菜單樹,分類樹,部門樹等等,如果為每種類型都遍歷遞歸生成樹形結(jié)構(gòu)返回給前端,顯得有些冗余且麻煩,并且其實(shí)邏輯都是一致的,只是遍歷的對(duì)象不同而已,故其實(shí)可以通過面向接口思維,來實(shí)現(xiàn)這種通用工具類的實(shí)現(xiàn)。

TreeNode用來表示每個(gè)樹節(jié)點(diǎn)的抽象,即需要生成樹的對(duì)象需要實(shí)現(xiàn)此接口。

 /**
   * 樹節(jié)點(diǎn)父類,所有需要使用{@linkplain TreeUtils}工具類形成樹形結(jié)構(gòu)等操作的節(jié)點(diǎn)都需要實(shí)現(xiàn)該接口
   *
   * @param <T> 節(jié)點(diǎn)id類型
   */
  public interface TreeNode<T> {
    /**
     * 獲取節(jié)點(diǎn)id
     *
     * @return 樹節(jié)點(diǎn)id
     */
    T id();
    /**
     * 獲取該節(jié)點(diǎn)的父節(jié)點(diǎn)id
     *
     * @return 父節(jié)點(diǎn)id
     */
    T parentId();
    /**
     * 是否是根節(jié)點(diǎn)
     *
     * @return true:根節(jié)點(diǎn)
     */
    boolean root();
    /**
     * 設(shè)置節(jié)點(diǎn)的子節(jié)點(diǎn)列表
     *
     * @param children 子節(jié)點(diǎn)
     */
    void setChildren(List<? extends TreeNode<T>> children);
    /**
     * 獲取所有子節(jié)點(diǎn)
     *
     * @return 子節(jié)點(diǎn)列表
     */
    List<? extends TreeNode<T>> getChildren();
  }

TreeUtils用來生成樹形結(jié)構(gòu),以及獲取所有葉子節(jié)點(diǎn)等操作

/**
 * 樹形結(jié)構(gòu)工具類
 *
 * @author meilin.huang
 * @version 1.0
 * @date 2019-08-24 1:57 下午
 */
public class TreeUtils {
  /**
   * 根據(jù)所有樹節(jié)點(diǎn)列表,生成含有所有樹形結(jié)構(gòu)的列表
   *
   * @param nodes 樹形節(jié)點(diǎn)列表
   * @param <T>  節(jié)點(diǎn)類型
   * @return 樹形結(jié)構(gòu)列表
   */
  public static <T extends TreeNode<?>> List<T> generateTrees(List<T> nodes) {
    List<T> roots = new ArrayList<>();
    for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
      T node = ite.next();
      if (node.root()) {
        roots.add(node);
        // 從所有節(jié)點(diǎn)列表中刪除該節(jié)點(diǎn),以免后續(xù)重復(fù)遍歷該節(jié)點(diǎn)
        ite.remove();
      }
    }
    roots.forEach(r -> {
      setChildren(r, nodes);
    });
    return roots;
  }
  /**
   * 從所有節(jié)點(diǎn)列表中查找并設(shè)置parent的所有子節(jié)點(diǎn)
   *
   * @param parent 父節(jié)點(diǎn)
   * @param nodes 所有樹節(jié)點(diǎn)列表
   */
  @SuppressWarnings("all")
  public static <T extends TreeNode> void setChildren(T parent, List<T> nodes) {
    List<T> children = new ArrayList<>();
    Object parentId = parent.id();
    for (Iterator<T> ite = nodes.iterator(); ite.hasNext(); ) {
      T node = ite.next();
      if (Objects.equals(node.parentId(), parentId)) {
        children.add(node);
        // 從所有節(jié)點(diǎn)列表中刪除該節(jié)點(diǎn),以免后續(xù)重復(fù)遍歷該節(jié)點(diǎn)
        ite.remove();
      }
    }
    // 如果孩子為空,則直接返回,否則繼續(xù)遞歸設(shè)置孩子的孩子
    if (children.isEmpty()) {
      return;
    }
    parent.setChildren(children);
    children.forEach(m -> {
      // 遞歸設(shè)置子節(jié)點(diǎn)
      setChildren(m, nodes);
    });
  }
  /**
   * 獲取指定樹節(jié)點(diǎn)下的所有葉子節(jié)點(diǎn)
   *
   * @param parent 父節(jié)點(diǎn)
   * @param <T>  實(shí)際節(jié)點(diǎn)類型
   * @return 葉子節(jié)點(diǎn)
   */
  public static <T extends TreeNode<?>> List<T> getLeafs(T parent) {
    List<T> leafs = new ArrayList<>();
    fillLeaf(parent, leafs);
    return leafs;
  }
  /**
   * 將parent的所有葉子節(jié)點(diǎn)填充至leafs列表中
   *
   * @param parent 父節(jié)點(diǎn)
   * @param leafs 葉子節(jié)點(diǎn)列表
   * @param <T>  實(shí)際節(jié)點(diǎn)類型
   */
  @SuppressWarnings("all")
  public static <T extends TreeNode> void fillLeaf(T parent, List<T> leafs) {
    List<T> children = parent.getChildren();
    // 如果節(jié)點(diǎn)沒有子節(jié)點(diǎn)則說明為葉子節(jié)點(diǎn)
    if (CollectionUtils.isEmpty(children)) {
      leafs.add(parent);
      return;
    }
    // 遞歸調(diào)用子節(jié)點(diǎn),查找葉子節(jié)點(diǎn)
    for (T child : children) {
      fillLeaf(child, leafs);
    }
  }
}

具體使用方式之聲明樹節(jié)點(diǎn)對(duì)象

@Getter
@Setter
public class ResourceListVO implements TreeNode<Long> {
  private Long id;
  private Long pid;
  private Integer type;
  private String name;
  private String icon;
  private String code;
  private Integer status;
  private List<ResourceListVO> children;
  @Override
  public Long id() {
    return this.id;
  }
  @Override
  public Long parentId() {
    return this.pid;
  }
  @Override
  public boolean root() {
    return Objects.equals(this.pid, 0L);
  }
  @Override
  public void setChildren(List children) {
    this.children = children;
  }
}

具體使用方式之調(diào)用

 /**
  * 獲取賬號(hào)的資源樹
  */
  public List<ResourceListVO> listByAccountId(Long accountId) {
    return TreeUtils.generateTrees(BeanUtils.copyProperties(mapper.selectByAccountId(userId), ResourceListVO.class));
  }

通過使用TreeUtils工具可以統(tǒng)一方便地生成一切對(duì)象的樹形結(jié)構(gòu)以及其他一些對(duì)樹的操作,避免對(duì)每個(gè)對(duì)象都用特定代碼生成。使用起來就是幾個(gè)字簡潔方便爽歪歪biu特否。

補(bǔ)充知識(shí):TreeUtil 數(shù)據(jù)庫菜單生成無限級(jí)樹形結(jié)構(gòu)

1、項(xiàng)目需求:

從數(shù)據(jù)庫從加載所有的菜單出來,菜單中有

id,parentId,name字段

希望能有一個(gè)工具幫我進(jìn)行樹形結(jié)構(gòu)重組;

實(shí)例類:

package com.lming.chcservice.util; 
import lombok.Data; 
import java.util.List;
@Data
public class TreeNode {
  /**
   * 節(jié)點(diǎn)id
   */
  private String id;
  /**
   * 父節(jié)點(diǎn) 默認(rèn)0為根節(jié)點(diǎn)
   */
  private String parentId;
  /**
   * 節(jié)點(diǎn)名稱
   */
  private String name;
  /**
   * 是否有子節(jié)點(diǎn)
   */
  private boolean hasChild;
 
  public TreeNode(String id, String parentId, String name) {
    this.id = id;
    this.parentId = parentId;
    this.name = name;
  }
}

工具類:

package com.lming.chcservice.util;
 
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
 
/**
 * 樹形結(jié)構(gòu)工具類
 *
 * 將一組list對(duì)象轉(zhuǎn)成樹形結(jié)構(gòu)
 * 該list需符合設(shè)定的字段類型
 *
 */
public class TreeUtil { 
 
  public static Map<String,Object> mapArray = new LinkedHashMap<String, Object>(); 
  public List<TreeNode> menuCommon;
  public List<Object> list = new ArrayList<Object>();
 
  public List<Object> treeMenu(List<TreeNode> menu){
    this.menuCommon = menu;
    for (TreeNode treeNode : menu) {
      Map<String,Object> mapArr = new LinkedHashMap<String, Object>();
      if(treeNode.getParentId().equals("0")){
        setTreeMap(mapArr,treeNode);
        list.add(mapArr);
      }
    }
    return list;
  }
 
  public List<?> menuChild(String id){
    List<Object> lists = new ArrayList<Object>();
    for(TreeNode a:menuCommon){
      Map<String,Object> childArray = new LinkedHashMap<String, Object>();
      if(a.getParentId() .equals(id)){
        setTreeMap(childArray,a);
        lists.add(childArray);
      }
    }
    return lists;
  }
 
  private void setTreeMap(Map<String,Object> mapArr,TreeNode treeNode){
    mapArr.put("id", treeNode.getId());
    mapArr.put("name", treeNode.getName());
    mapArr.put("parentId", treeNode.getParentId());
    List<?> childrens = menuChild(treeNode.getId());
    if(childrens.size()>0){
      mapArr.put("hasChild",true);
    }
    else{
      mapArr.put("hasChildren",false);
    }
    mapArr.put("childrens", menuChild(treeNode.getId()));
  }
 
  public static void main(String[] args){
 
    List<TreeNode> treeNodeList = new ArrayList<>();
    TreeNode treeNode1 = new TreeNode("1","0","首頁");
    TreeNode treeNode2 = new TreeNode("2","0","訂單");
    TreeNode treeNode3 = new TreeNode("3","1","預(yù)約");
    TreeNode treeNode4 = new TreeNode("4","2","捐獻(xiàn)");
    TreeNode treeNode5 = new TreeNode("5","4","我的訂單");
    TreeNode treeNode6 = new TreeNode("6","5","個(gè)人中心");
    TreeNode treeNode7 = new TreeNode("7","6","個(gè)人中心2");
    TreeNode treeNode8 = new TreeNode("8","99","個(gè)人中心3");
    treeNodeList.add(treeNode1);
    treeNodeList.add(treeNode6);
    treeNodeList.add(treeNode5);
    treeNodeList.add(treeNode3);
    treeNodeList.add(treeNode4);
    treeNodeList.add(treeNode2);
    treeNodeList.add(treeNode7);
    treeNodeList.add(treeNode8); 
 
    TreeUtil treeUtil = new TreeUtil();
    System.out.print(JsonUtil.toJson(treeUtil.treeMenu(treeNodeList))); 
  } 
}

測(cè)試結(jié)果:

[
 {
  "id": "1",
  "name": "首頁",
  "parentId": "0",
  "hasChild": true,
  "childrens": [
   {
    "id": "3",
    "name": "預(yù)約",
    "parentId": "1",
    "hasChildren": false,
    "childrens": []
   }
  ]
 },
 {
  "id": "2",
  "name": "訂單",
  "parentId": "0",
  "hasChild": true,
  "childrens": [
   {
    "id": "4",
    "name": "捐獻(xiàn)",
    "parentId": "2",
    "hasChild": true,
    "childrens": [
     {
      "id": "5",
      "name": "我的訂單",
      "parentId": "4",
      "hasChild": true,
      "childrens": [
       {
        "id": "6",
        "name": "個(gè)人中心",
        "parentId": "5",
        "hasChild": true,
        "childrens": [
         {
          "id": "7",
          "name": "個(gè)人中心2",
          "parentId": "6",
          "hasChildren": false,
          "childrens": []
         }
        ]
       }
      ]
     }
    ]
   }
  ]
 }
]

實(shí)力類不一致怎么辦? 自己寫一個(gè)實(shí)體轉(zhuǎn)換類,將類的對(duì)象屬性轉(zhuǎn)換成上面的實(shí)體類,然后在調(diào)用,當(dāng)然最快的方式直接修改實(shí)體類即可用。

以上這篇java之TreeUtils生成一切對(duì)象樹形結(jié)構(gòu)案例就是小編分享給大家的全部內(nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • IDEA創(chuàng)建Java?Web項(xiàng)目的超詳細(xì)圖文教學(xué)

    IDEA創(chuàng)建Java?Web項(xiàng)目的超詳細(xì)圖文教學(xué)

    IDEA是程序員們常用的java集成開發(fā)環(huán)境,也是被公認(rèn)為最好用的java開發(fā)工具,下面這篇文章主要給大家介紹了關(guān)于IDEA創(chuàng)建Java?Web項(xiàng)目的相關(guān)資料,文中通過圖文介紹的非常詳細(xì),需要的朋友可以參考下
    2022-12-12
  • 詳解Java設(shè)計(jì)模式——迭代器模式

    詳解Java設(shè)計(jì)模式——迭代器模式

    這篇文章主要介紹了Java設(shè)計(jì)模式——迭代器模式,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-03-03
  • Java經(jīng)典快排思想以及快排的改進(jìn)講解

    Java經(jīng)典快排思想以及快排的改進(jìn)講解

    今天小編就為大家分享一篇關(guān)于Java經(jīng)典快排思想以及快排的改進(jìn)講解,小編覺得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來看看吧
    2019-01-01
  • java8 stream中Collectors.toMap空指針問題及解決

    java8 stream中Collectors.toMap空指針問題及解決

    這篇文章主要介紹了java8 stream中Collectors.toMap空指針問題及解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-05-05
  • Java基礎(chǔ)之集合Set詳解

    Java基礎(chǔ)之集合Set詳解

    這篇文章主要介紹了Java基礎(chǔ)之集合Set詳解,文中有非常詳細(xì)的代碼示例,對(duì)正在學(xué)習(xí)java基礎(chǔ)的小伙伴們有很好地幫助,需要的朋友可以參考下
    2021-05-05
  • mybatis通過中間表實(shí)現(xiàn)一對(duì)多查詢功能

    mybatis通過中間表實(shí)現(xiàn)一對(duì)多查詢功能

    這篇文章主要介紹了mybatis通過中間表實(shí)現(xiàn)一對(duì)多查詢,通過一個(gè)學(xué)生的id查詢出該學(xué)生所學(xué)的所有科目,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下
    2021-08-08
  • Java實(shí)現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法示例

    Java實(shí)現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法示例

    這篇文章主要介紹了Java實(shí)現(xiàn)輸出回環(huán)數(shù)(螺旋矩陣)的方法,涉及java針對(duì)數(shù)組的遍歷、判斷、輸出等相關(guān)操作技巧,需要的朋友可以參考下
    2017-12-12
  • Mybatis批量插入index out of range錯(cuò)誤的解決(較偏的錯(cuò)誤)

    Mybatis批量插入index out of range錯(cuò)誤的解決(較偏的錯(cuò)誤)

    這篇文章主要介紹了Mybatis批量插入index out of range錯(cuò)誤的解決(較偏的錯(cuò)誤),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java語言中的自定義類加載器實(shí)例解析

    Java語言中的自定義類加載器實(shí)例解析

    這篇文章主要介紹了Java語言中的自定義類加載器實(shí)例解析,分享了相關(guān)代碼示例,小編覺得還是挺不錯(cuò)的,具有一定借鑒價(jià)值,需要的朋友可以參考下
    2018-02-02
  • Java使用策略模式解決商場(chǎng)促銷商品問題示例

    Java使用策略模式解決商場(chǎng)促銷商品問題示例

    這篇文章主要介紹了Java使用策略模式解決商場(chǎng)促銷商品問題,簡單描述了策略模式的概念、原理,并結(jié)合實(shí)例形式分析了Java基于策略模式解決商品促銷問題的相關(guān)操作技巧,需要的朋友可以參考下
    2018-05-05

最新評(píng)論

临漳县| 上虞市| 区。| 讷河市| 桦甸市| 于田县| 瑞丽市| 双辽市| 德阳市| 佛学| 石柱| 湟源县| 淅川县| 米泉市| 乌拉特后旗| 乌拉特后旗| 九台市| 南木林县| 基隆市| 无锡市| 日土县| 京山县| 阳朔县| 定西市| 安溪县| 和林格尔县| 军事| 炉霍县| 漯河市| 阿勒泰市| 壶关县| 西昌市| 辉县市| 石景山区| 邯郸市| 清水县| 长海县| 府谷县| 太和县| 通榆县| 登封市|