Lambda表达式 去重---多人员多角色新增删除记录

场景:使用审计日志 对角色权限进行修改信息的记录,将数据封装进对应的填充信息,由于会使用到userModify,针对用户批量修改 添加、删除角色,这时候就需要 先做删除逻辑判断出 角色信息,再坐新增逻辑 添加对应角色。 整理一下,会出现以下情况,多个人员 Person 有不同工号,需要修改 可能相同的角色  也可能不同, 删除 可能相同 也可能不同的角色。

举例:存在 人员Byron:A B C roleCode需要删除   新增BA的roleCode  PesronId 1
                           test   删除 A roleCode  PersonId 2
                           Ftest 新增 voidF  PersonId 3

        AuditLogUserRoleTO A = new AuditLogUserRoleTO();
        AuditLogUserRoleTO B = new AuditLogUserRoleTO();
        AuditLogUserRoleTO C = new AuditLogUserRoleTO();
        AuditLogUserRoleTO D = new AuditLogUserRoleTO();
        AuditLogUserRoleTO F = new AuditLogUserRoleTO();
        AuditLogUserRoleTO BA = new AuditLogUserRoleTO();

        A.setDeleteRole("A");
        A.setUserName("Byron");
        A.setPersonId("1");

        BeanUtils.copyProperties(A,B);
        B.setDeleteRole("B");

        BeanUtils.copyProperties(A,C);
        C.setDeleteRole("C");

        BeanUtils.copyProperties(A,D);
        D.setUserName("test");
        D.setPersonId("2");

        BA.setAddRole("BA");
        BA.setUserName("Byron");
        BA.setPersonId("1");

        F.setAddRole("voidF");
        F.setUserName("Ftest");
        F.setPersonId("3");

根据当前的人员信息 汇总出一套 需要删除的 LIst<> deleteData 集合 和 List<> addData集合

        List<AuditLogUserRoleTO> deleteData = new ArrayList<AuditLogUserRoleTO>();
        List<AuditLogUserRoleTO> addData = new ArrayList<AuditLogUserRoleTO>();
        deleteData.add(A);
        deleteData.add(B);
        deleteData.add(C);
        deleteData.add(D);
        addData.add(BA);
        addData.add(F);
        System.out.println(deleteData);
        System.out.println(addData);

deleteData:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=A, addRole=null), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=B, addRole=null), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=C, addRole=null), AuditLogUserRoleTO(userName=test, personId=2, deleteRole=A, addRole=null)]

addData:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=null, addRole=BA), AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=null, addRole=voidF)]

去重逻辑开始

根据新增角色,对删除角色去重,以人员UserName为标准,并返回List<>集合

        List<AuditLogUserRoleTO> list = addData.stream().
                filter(
                        e -> !deleteData.stream().map(AuditLogUserRoleTO::getUserName).collect(Collectors.toList())
                                .contains(e.getUserName()))
                .collect(Collectors.toList());

        System.out.println(list);

List<>返回信息:由于根据UserName求差集,add:Byron Ftest 针对delete:Byron test 求差集得到Ftest
[AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=null, addRole=voidF)]

由于数据此时是割裂的状态,需要将数据根据人员进行汇总成,删除、新增roleCode同时存在的信息

对deleteData遍历,更具UserName添加addRole

        List<AuditLogUserRoleTO> data = new ArrayList<>();
        for (AuditLogUserRoleTO delete : deleteData){
            for (AuditLogUserRoleTO add : addData){
                if (delete.getUserName().equals(add.getUserName())){
                    delete.setAddRole(add.getAddRole());
                }
            }
        }

汇总添加到deleteData的List中,因为最终是要形成审计信息的对象,将这个List<>丢进data中。

        deleteData.addAll(list);
        System.out.println("deleteData:++++:"+deleteData);
        data.addAll(deleteData);
        System.out.println(data);

        List<AuditLogUserRoleTO> tempList = new ArrayList<>();

此时汇总的deleteData 既携带了addRole 也携带了deleteRole,完整信息,存在重复,需要二次处理

deleteData:++++:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=A, addRole=BA), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=B, addRole=BA), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=C, addRole=BA), AuditLogUserRoleTO(userName=test, personId=2, deleteRole=A, addRole=null), AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=null, addRole=voidF)]

把信息添加到最终发往记录信息用的data中:

data:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=A, addRole=BA), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=B, addRole=BA), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=C, addRole=BA), AuditLogUserRoleTO(userName=test, personId=2, deleteRole=A, addRole=null), AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=null, addRole=voidF)]

这里穿件了一个tempList是为了防止对原数据处理引起不必要的麻烦,用一个临时信息作为真正需要计入审计信息的内容

对这时候的data遍历,获取人员UserName,并且将对应的角色放进sb1,sb2的HashSet中,这里采用HashSet的原因是:原来使用StringBuilder,会把遍历过程中重复出现的新增或删除roleCode,不断拼接添加进去,这样最终打印显示会出现重复。HashSet本身可以进行去重,解决该问题。

        //StringBuilder sb1 = new StringBuilder();
        //StringBuilder sb2 = new StringBuilder();

        if (CollectionUtils.isEmpty(data)){
            return;
        }
        for (AuditLogUserRoleTO audit : data){
            HashSet sb1 = new HashSet();
            HashSet sb2 = new HashSet();
            AuditLogUserRoleTO temp = new AuditLogUserRoleTO();
            temp.setUserName(audit.getUserName());
            for (AuditLogUserRoleTO logTO : data){
                if (audit.getUserName().equals(logTO.getUserName())){

                        sb1.add(StringUtils.isBlank(logTO.getAddRole()) ? "" : logTO.getAddRole());

                        sb2.add(StringUtils.isBlank(logTO.getDeleteRole()) ? "" : logTO.getDeleteRole());

                }
            }
            temp.setAddRole(sb1.toString());
            temp.setDeleteRole(sb2.toString());
            tempList.add(temp);
        }

把信息丢给sb1,sb2处理后,保证去重唯一,针对人员添加,对temp信息设置对应的新增,删除roleCode,给到最终的tempList,即实际传给审计处理信息。

因为上面的tempList仍然存在重复数据,原因是data是根据UserName循环设置的,上面最初设置时候,还没有对人去重,所以这个data重复,但保证了删除,添加role信息的统一。

需要再次进行去重操作,获取最终的result信息

        System.out.println("tempList:"+tempList);
        // 去重
        List<AuditLogUserRoleTO> result = tempList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(AuditLogUserRoleTO::getUserName))),
                        ArrayList::new
                )
        );
        System.out.println("result:"+result);
        for (AuditLogUserRoleTO auditLogUserRoleTO : result) {
            String addRole = auditLogUserRoleTO.getAddRole();
            String deleteRole = auditLogUserRoleTO.getDeleteRole();
            System.out.println("addRole"+(StringUtils.isBlank(addRole) ? "" : addRole));
            System.out.println("deleteRole"+(StringUtils.isBlank(deleteRole) ? "" : deleteRole));
        }

打印tempList信息,这时候将所有角色RoleCode汇总,但是因为根据userName,存在重复

tempList:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=[A, B, C], addRole=[BA]), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=[A, B, C], addRole=[BA]), AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=[A, B, C], addRole=[BA]), AuditLogUserRoleTO(userName=test, personId=2, deleteRole=[A], addRole=[]), AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=[], addRole=[voidF])]
 

最终去重结果result,如下所示,通过collection相关操作得到,具体说明使用见最后

result:

[AuditLogUserRoleTO(userName=Byron, personId=1, deleteRole=[A, B, C], addRole=[BA]), AuditLogUserRoleTO(userName=Ftest, personId=3, deleteRole=[], addRole=[voidF]), AuditLogUserRoleTO(userName=test, personId=2, deleteRole=[A], addRole=[])]


addRole[BA]
deleteRole[A, B, C]
addRole[voidF]
deleteRole[]
addRole[]
deleteRole[A]

这样一来就能把所有的信息完成去重,并且提供相对准确,且待分隔的role信息。
 

参考以下做去重的lambda:
java8 stream两个集体交集、差集、并集操作 - 走看看

最后这一部分collectingAndThen的去重理解 记录一下
使用到了 collectingAndThen、toCollection、TreeSet这几点

核心在于:使用TreeSet去重,将TreeSet转换为List,这个理需要传入一个属性来比较作为比较器,使用public ArrayList<Collection<? extends E>c>将TreeSet放入构造器生成List
 

        List<AuditLogUserRoleTO> result = tempList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(Comparator.comparing(AuditLogUserRoleTO::getUserName))),
                        ArrayList::new
                )
        );

这一部分,可以使用普通集合:

TreeSet<AuditLogUserRoleTO> treeSet = new TreeSet<>(Comparator.comparing(AuditLogUserRoleTO::getUserName)));

for(AuditLogUserRoleTO tempData : tempList){
        treeSet.add(tempData);
}
List<AuditLogUserRoleTO> result = new ArrayList<>(treeSet);

只要能够理解普通集合操作,name使用Stream流操作是,就要看对于API的使用是否熟悉,其实这个,这里需要理解collectingAndThen、toCollection、JDK8匿名函数。

关于collectingAndThen方法使用-----首先进行结果集的收集,然后将收集到的结果集进行下一步处理,看一下该信息需要传递的参数:

public static <T, A, R, RR> Collector<T, A, RR> collectingAndThen(Collector<T, A, R> var0, Function<R, RR> var1) {
        Set var2 = var0.characteristics();
        if (var2.contains(Characteristics.IDENTITY_FINISH)) {
            if (var2.size() == 1) {
                var2 = CH_NOID;
            } else {
                EnumSet var3 = EnumSet.copyOf(var2);
                var3.remove(Characteristics.IDENTITY_FINISH);
                var2 = Collections.unmodifiableSet(var3);
            }
        }

        return new Collectors.CollectorImpl(var0.supplier(), var0.accumulator(), var0.combiner(), var0.finisher().andThen(var1), var2);
    }

上面是它的源码,是Collector接口子类,所以还是对于Collector的处理,工具类中存在toList()、toSet、joining()、mapping()、collectingAndThen()等,几乎所有方法都可以使用,可以进行嵌套使用。第二个参数是一个Function函数,R apply(T t),这个是去重关键,ArrayList::new 调用的实参构造方法。

这里相当于通过Comparator获取去重内容,交给第二个参数Function函数,作为参数得到结果,就是Rapply(T t),将这个Comparator结果作为t放入。

对于toCollection是一个通过转换为集合的操作,在Collectors类里也有toList、toSet方法,但是不满足使用TreeSet获取集合,使用toCollection是一个通用方法,使用TreeSet收集,根据属性进行比较器比较,达到最终效果。

以上就是实现整个业务场景实现去重操作的过程其中,最后关于Collection这部分参考了,以下帖子,部分内容就是由他而来。

JDK8 Stream操作 collectingAndThen ------根据对象的属性进行去重操作_goodluckwj的博客-CSDN博客_collectingandthen

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值