栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

Java获取一棵树的3种方法

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

Java获取一棵树的3种方法

树在很多地方都会用到,比如权限菜单、省市县等等,思路就是先把列表查出来,然后再生成一棵树

目录

数据初始化(必看)

方法一:使用递归生成树

方法二:非递归生成树

方法三:封装第二种方法(cv直接看这种)


数据初始化(必看)

初始化城市对象

public class City {
	
	private Integer cityId;

	
	private String cityName;

	
	private Integer parentId;

	
	private List children;

	
	public City(Integer cityId, String cityName, Integer parentId) {
		this.cityId = cityId;
		this.cityName = cityName;
		this.parentId = parentId;
	}

	// 省略get、set
}

初始化数据

// 初始化城市信息
List cityList = new linkedList<>() {{
   add(new City(1, "福建省", 0));
   add(new City(2, "浙江省", 0));
   add(new City(3, "江苏省", 0));
   add(new City(4, "厦门市", 1));
   add(new City(5, "漳州市", 1));
   add(new City(6, "泉州市", 1));
   add(new City(7, "集美区", 4));
   add(new City(8, "同安区", 4));
   add(new City(9, "金华市", 2));
}};

// 要获取的节点id
// 在这里,0表示所有省份,1表示福建省下的所有市,以此类推
final Integer parentId = 0;

// 生成一棵树(getTree方法一会儿会实现)
List treeList = getTree(cityList, parentId);

方法一:使用递归生成树
public static List getTree(List list, Integer parentId) {
   // 获取兄弟
   List brotherList = list.stream().filter(city -> city.getParentId().equals(parentId)).collect(Collectors.toList());
   // 获取上面这些兄弟的后代
   List childrenList = list.stream().filter(city -> !city.getParentId().equals(parentId)).collect(Collectors.toList());

   // 遍历兄弟
   brotherList.forEach(brother -> {
      // 遍历兄弟的后代
      childrenList.forEach(child -> {
         // 如果找到了兄弟的孩子
         if (child.getParentId().equals(brother.getCityId())) {
            // 如果children为空,就让它等于new linkedList<>()
            brother.setChildren(Optional.ofNullable(brother.getChildren()).orElse(new linkedList<>()));
            // 把兄弟的孩子添加进去
            brother.getChildren().add(child);
         }
      });
   });

   // 遍历兄弟,递归获取兄弟的孩子
   brotherList.forEach(brother -> getTree(childrenList, brother.getCityId()));
   // 返回兄弟们
   return brotherList;
}

方法二:非递归生成树

相比递归,其实更推荐这种方法,这种方其实两次遍历list就好了,第一次遍历是根据parentId在map里面进行分组,第二次是根据id,去map找它的孩子,这样说可能还是有些人还是不太理解,代码写出来,打个断点研究一下就一目了然了

private static List getTree2(List list, Integer parentId) {
   // 存放按parentId分组的数据
   Map> map = new linkedHashMap<>();

   list.forEach(city -> {
      // 取出同一个父亲下的兄弟
      List brotherList = map.get(city.getParentId());
      // 判断非空
      brotherList = brotherList == null ? new linkedList<>() : brotherList;
      // 加入到兄弟里面
      brotherList.add(city);
      // 把兄弟们重新放到map里面
      map.put(city.getParentId(), brotherList);
   });

   list.forEach(city -> {
      // 去map找它孩子
      List childrenList = map.get(city.getCityId());
      // 把它的孩子丢进去
      city.setChildren(childrenList);
   });
   return map.get(parentId);
}

方法三:封装第二种方法(cv直接看这种)

可能有些人看到这些算法的代码会脑阔疼,这里把第二种方法封装起来,然后小改动一下就可以

新建一个类

public abstract class Tree {
	
	private Serializable id;

	
	private Serializable parentId;

	
	private List children = new ArrayList<>();
	
	// 省略get、set
}

要生成的对象继承这个类

public class City extends Tree {
    ...
}

根据以下注释进行修改

public class City extends Tree {
	// 如果有children字段,则把children字段去掉,会和父类的冲突
	// private List children;

	public City(Integer cityId, String cityName, Integer parentId) {
		this.cityId = cityId;
		this.cityName = cityName;
		this.parentId = parentId;

		// 给父类赋值上id
		super.setId(cityId);
		// 给父类赋上parentId
		super.setParentId(this.parentId);
	}

	public void setCityId(Integer cityId) {
		this.cityId = cityId;
		// 给父类赋上id
		super.setId(cityId);
	}

	public void setParentId(Integer parentId) {
		this.parentId = parentId;
		// 给父类赋上parentId
		super.setParentId(parentId);
	}

    ...
}

获取一棵树,核心方法,直接cv

private static  List getTree(List list, Serializable parentId) {
   Map> map = new linkedHashMap<>();

   // 根据parentId进行分组
   for (T t : list) {
      // 取出同一个父亲下的兄弟
      List list2 = map.get(t.getParentId());
      // 判断非空
      list2 = list2 == null ? new linkedList<>() : list2;
      // 加入到兄弟里面
      list2.add(t);
      // 把兄弟们重新放到map里面
      map.put(t.getParentId(), list2);
   }

   for (T t : list) {
      // 去map找它孩子
      List list2 = map.get(t.getId());
      // 把它孩子丢进去
      t.setChildren(list2);
   }
   return map.get(parentId);
}

 直接调用

List treeList = getTree(cityList, parentId);

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/345395.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号