递归和迭代算法分别查询父类下边的子类,及子类下边子类

首先测试bean类:

@Data
public class BeanTest1 {

    private Integer id;
    private Integer parentId;
    private String name;

    private List<BeanTest1> children = new LinkedList<>();

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

加入数据

List<BeanTest1> beanTest1List = new LinkedList<>();
beanTest1List.add(new BeanTest1(1,0,"1"));
beanTest1List.add(new BeanTest1(2,1,"2"));
beanTest1List.add(new BeanTest1(3,1,"3"));
beanTest1List.add(new BeanTest1(4,1,"4"));
beanTest1List.add(new BeanTest1(5,0,"5"));
beanTest1List.add(new BeanTest1(6,5,"6"));
beanTest1List.add(new BeanTest1(7,6,"7"));

Map<Integer, List<BeanTest1>> integerListMap = countChildren2(beanTest1List);

integerListMap.forEach((k,v) -> {
    System.out.println(k+"---"+v);
});

一、只有父类包含子类,子类没有子类的情况:

递归算法:

Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();

public Map<BeanTest1, List<BeanTest1>> countChildrenRecursive(List<BeanTest1> beanTest1List) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getParentId() == null) {
            continue;
        }
        if (!result.containsKey(bean)) {
            result.put(bean, new ArrayList<>());
        }
        result.get(bean).addAll(countChildrenRecursive(bean.getChildren()).get(bean));
    }
    return result;
}

迭代算法:

Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();

public Map<BeanTest1, List<BeanTest1>> countChildrenIterative(List<BeanTest1> beanTest1List) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getParentId() == null) {
            continue;
        }
        BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
        if (!result.containsKey(parent)) {
            result.put(parent, new ArrayList<>());
        }
        result.get(parent).add(bean);
    }
    return result;
}

public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getId().equals(parentId)) {
            return bean;
        }
    }
    return null;
}

二、不仅父类包含子类,子类也有子类的情况:

递归算法:

如果子类也有子类,可以在递归算法中继续调用自身,直到所有子类都遍历完为止。

Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();

public Map<BeanTest1, List<BeanTest1>> countChildrenRecursive(List<BeanTest1> beanTest1List) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getParentId() == null) {
            continue;
        }
        BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
        if (!result.containsKey(parent)) {
            result.put(parent, new ArrayList<>());
        }
        result.get(parent).add(bean);
        if (!bean.getChildren().isEmpty()) {
            countChildrenRecursive(bean.getChildren());
        }
    }
    return result;
}

public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getId().equals(parentId)) {
            return bean;
        }
    }
    return null;
}

在这里,我们首先判断子类是否有子类,如果有就继续调用countChildrenRecursive方法。

迭代算法

Map<BeanTest1, List<BeanTest1>> result = new HashMap<>();
Queue<BeanTest1> queue = new LinkedList<>();

public Map<BeanTest1, List<BeanTest1>> countChildrenIterative(List<BeanTest1> beanTest1List) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getParentId() == null) {
            queue.offer(bean);
        }
    }
    while (!queue.isEmpty()) {
        BeanTest1 parent = queue.poll();
        if (!result.containsKey(parent)) {
            result.put(parent, new ArrayList<>());
        }
        result.get(parent).addAll(parent.getChildren());
        queue.addAll(parent.getChildren());
    }
    return result;
}

迭代算法中我们将父类加入队列中进行迭代遍历,遍历到的子类也加入队列中继续遍历,直到所有类都被遍历完为止。

这种方法有个缺点是需要使用额外的队列来存储遍历过的对象,会占用额外的空间。

另外,在这种情况下,我们需要确保 BeanTest1 类中有 getChildren() 方法,并且每个 BeanTest1 对象的 children 属性已经被初始化。

请注意:如果parentId=0的时候,会出现一个key为null,也就是0为父类的情况,实际应用中请自行忽略及更改

以上输出长这样:

null---[BeanTest1(id=1, parentId=0, name=1, children=null), BeanTest1(id=5, parentId=0, name=5, children=null)]
BeanTest1(id=6, parentId=5, name=6, children=null)---[BeanTest1(id=7, parentId=6, name=7, children=null)]
BeanTest1(id=1, parentId=0, name=1, children=null)---[BeanTest1(id=2, parentId=1, name=2, children=null), BeanTest1(id=3, parentId=1, name=3, children=null), BeanTest1(id=4, parentId=1, name=4, children=null)]
BeanTest1(id=5, parentId=0, name=5, children=null)---[BeanTest1(id=6, parentId=5, name=6, children=null)]

也有返回值是List的,最外层都是parentId为0的,然后数据存在children中

List<BeanTest1> result = new ArrayList<>();

public List<BeanTest1> countChildren(List<BeanTest1> beanTest1List) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getParentId() == 0) {
            result.add(bean);
        } else {
            BeanTest1 parent = findParent(beanTest1List, bean.getParentId());
            parent.getChildren().add(bean);
        }
    }
    return result;
}

public BeanTest1 findParent(List<BeanTest1> beanTest1List, Integer parentId) {
    for (BeanTest1 bean : beanTest1List) {
        if (bean.getId().equals(parentId)) {
            return bean;
        }
    }
    return null;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值