java 集合封装树形结构

该博客介绍了如何在Java中构建树形结构,通过遍历节点并检查parentId来实现父子节点的封装。在过程中,作者遇到了入参集合被修改的问题,并提供了解决方案——使用BeanUtils复制对象以保持原集合不变。文章强调了正确引用的重要性,并分享了避免原集合被修改的代码示例。
摘要由CSDN通过智能技术生成

本例父子关系,子节点的parentId和父节点的id相同。

实现树形排列的方法

    public static List<Type> buildTree(List<Type> treeNodes) {
        List<Type> trees = new ArrayList<>();
        for (Type treeNode : treeNodes) {        // 第一层遍历,对每一个节点(目标)做一次父亲,找其孩子节点,进行封装
        	// 需要知道根节点的特征,遍历到根节点就可以封装到trees中(根节点就不会在有上层了),本例根节点parentId为空
            if (StringUtils.isBlank(treeNode.getParentId())) {
                trees.add(treeNode);
            }
            for (Type it : treeNodes) {   // 第二层遍历全部,校验是否是(目标)的孩子节点,进行父子封装
                if (Objects.equals(it.getParentId(), treeNode.getId())) {
                    if (treeNode.getChildList() == null) {
                        treeNode.setChildList(new ArrayList<Type>());   // 防止空指针
                    }
                    treeNode.getChildList().add(it);
                }
            }
        }
        return trees;
    }

实现原理:
集合可以理解为对多个对象的引用。本例中入参为treeNodes集合。不管在后面的for循环还是add方法中,实际只是对trees(必须new出来,不能直接用treeNodes赋值)集合的组装,对于treeNodes集合而言,每一个对象的引用和顺序至始至终没有发生任何改变,改变的仅仅是值发生改变,每一个值都包含了childList对象。对于trees而言,只含有根节点数量个对象。

遇到的问题:
在调用处,获取trees集合的同时,传入的treeNodes也会发生多出childList的改变。如果不希望入参的treeNodes发生这个改变,就需要入参集合与treeNodes集合引用不同的对象地址。
错误的赋值引用
List list2 = new ArrayList();
list2.addAll(treeNodes);
当list2作为入参后,执行过方法发现treeNodes还是多了childList的属性。因为这种方法对list2而言是新的引用没错,此时对list2进行增删操作也不会影响treeNodes。但是加入的对象确不行,引用是相同的,当Type改变值的时候,在treeNodes和list2中都会发生改变。当然List list2 =treeNodes;就更不正确了
在这里插入图片描述
正确的赋值引用
需要不仅对list对象new出来,还需要对其中的每一个对象new出来一遍。
如引用代码:
List list3 = copyList(list1, Type::new);
具体方法:

public static <S, T> List<T> copyList(List<S> sources, Supplier<T> target) {
        List<T> list = new ArrayList<>(sources.size());
        for (S source : sources) {
            T t = target.get();
            try {
                BeanUtils.copyProperties( t,source);
            } catch (Exception e) {
                e.printStackTrace();
            }
            list.add(t);
        }
        return list;
    }

在这里插入图片描述
可以看到,前面虽然值一样,但是实际的引用地址已经不同了。

学海无涯苦作舟!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值