java遍历树形结构

可能平常会遇到一些需求,比如构建菜单,构建树形结构,数据库一般就使用父id来表示,为了降低数据库的查询压力,我们可以使用Java8中的Stream流一次性把数据查出来,然后通过流式处理。

我们一起来看看,代码实现为了实现简单,就模拟查看数据库所有数据到List里面。

实体类:Menu.java

/**
 * 菜单类
 */
@Data
public class Menu {
	public Integer id;
	public String name;
	public Integer parentId;
	public List<Menu> childList;

	public Menu(Integer id, String name, Integer parentId) {
		this.id = id;
		this.name = name;
		this.parentId = parentId;
	}
}

方式一:使用stream 流

/**
 * 构造数据
 * @return
 */
public List<Menu> getMenuData() {
	List<Menu> menus = Lists.newArrayList();
	menus.add(new Menu(1, "根节点", 0));
	menus.add(new Menu(2, "子节点-1", 1));
	menus.add(new Menu(3, "节点-1.1", 2));
	menus.add(new Menu(4, "子节点-1.2", 2));
	menus.add(new Menu(5, "根节点-1.3", 2));
	menus.add(new Menu(6, "根节点-2", 1));
	menus.add(new Menu(7, "根节点-2.1", 6));
	menus.add(new Menu(8, "根节点-2.2", 6));
	menus.add(new Menu(9, "根节点-2.2.1", 7));
	menus.add(new Menu(10, "根节点-2.2.2", 7));
	menus.add(new Menu(11, "根节点-3", 1));
	menus.add(new Menu(12, "根节点-3.1", 11));
	menus.add(new Menu(13, "根节点-3.2", 11));
	menus.add(new Menu(14, "根节点-3.2.1", 13));
	return menus;
}

@Test
public void testMenuTree() {
	List<Menu> menuDatas = getMenuData();
	List<Menu> menuTree = menuDatas.stream().filter(m -> m.getParentId() == 0)
			.map((m) -> {
						m.setChildList(getChildrens(m, menuDatas));
						return m;
					}
			).collect(Collectors.toList());
	System.out.println("菜单树结构:" + JsonUtil.toJson(menuTree));
}


/**
 * 获取子类
 * @param parent
 * @param menuDatas
 * @return
 */
private List<Menu> getChildrens(Menu parent, List<Menu> menuDatas) {
	List<Menu> childList = menuDatas.stream().filter(m -> {
		return Objects.equals(m.getParentId(), parent.getId());
	}).map((m) -> {
		m.setChildList(getChildrens(m, menuDatas));
		return m;
	}).collect(Collectors.toList());
	return childList;
}

运行结果:

 方式二:使用原生的循环递归操作,这里使用iterator循环,设置完数据后移除,可以减少循环数据。

@Test
public void testMenu() {
	List<Menu> menuDatas = getMenuData();

	List<Menu> returnList = Lists.newArrayList();
	for (Iterator<Menu> lt = menuDatas.iterator(); lt.hasNext(); ) {
		Menu menu = lt.next();
		if (menu.getParentId() == 0) {
			returnList.add(menu);
			lt.remove();
		}
	}

	returnList.forEach(r -> {
		r.setChildList(getChild(r.getId(), menuDatas));
	});

	System.out.println("菜单树结构:" + JsonUtil.toJson(returnList));
}

private static List<Menu> getChild(Integer parentId, List<Menu> menuList) {
	List<Menu> childList = Lists.newArrayList();
	for (Iterator<Menu> lt = menuList.iterator(); lt.hasNext();){
		Menu menu = lt.next();
		if (parentId.equals(menu.getParentId())) {
			childList.add(menu);
			lt.remove();
		}
	}

	for (Menu menu : childList) {
		List<Menu> child = getChild(menu.getId(), menuList);
		menu.setChildList(child);
	}
	return childList;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值