• List对象集合根据组合属性进行差集运算


    背景

       当List是一个基本数据类型的集合的时候,进行集合运算还比较方便,但是有这么一些业务场景,比如某个用户权限变化的列表,或者取数据的变化结果,当时有时候用笨方法多循环两次也是可以的,只不过代码显得比较复杂,而且性能也不会太好。这次迭代我也就遇到这么一个需求。

    实现

       场景:我们系统用户是四个维度这样的数据,我们需要保存这样的数据,提供给前端一个这样的接口,前端传递用户相应的数据(用户组|职位|部门|用户),但是前端不会告诉我们,哪些是新增的,哪些是删除的,还有哪些没有变化,反正数据一股脑的给你,后端来自己组织。​当然,一般第一想法都是循环嘛,但是我一般的习惯都是将这种处理方法放在最后一个备选,实在想不出来好的方式才会使用最简单粗暴的方式哈哈哈。而且这个地方是要根据实体类里面的两个字段一起判断,无形中增加复杂度。List可以这样求差集(交并集类似):

    // 差集
    List<String> subList = list1.stream().filter(item -> list2.contains(item)).collect(toList());
    

       但这个List就一个String类型的,方便,而我们要判断的是两个对象是不是相等,简单嘛,一样这样使用嘛,那万一两个对象并不相同的,比如一个列表是从数据库中取出来的值,一个传出来的,它们的字段值都不同,那他们equals肯定也不同的,过滤后的值也不同,就会造成数据错误。

    // 考虑过滤数据,不进行重复更新
    List<SaveLibUserParam> saveLibUserParamList = param.getSaveLibUserParamList();
    List<UserCourseLibraryManage> originSaveList = Lists.newArrayList();
    if (Objects.nonNull(saveLibUserParamList) && saveLibUserParamList.size() > 0) {
    originSaveList = BeanConvertUtils.convertList(saveLibUserParamList, UserCourseLibraryManage.class);
    }
    // 查询出本来的旧数据
    List<UserCourseLibraryManage> list = userCourseLibraryManageDao.queryListByCompanyId(companyId);
    log.info("originList:{}", originSaveList);
    log.info("list:{}", list);
    // 需要本次新增的,即在origin中而list没有的
    // 需要本次删除的,即在origin没有而list中有的
    List<UserCourseLibraryManage> needAddList = originSaveList.stream().filter(item -> !list.contains(item)).collect(Collectors.toList());
    List<UserCourseLibraryManage> finalOriginSaveList = originSaveList;
    List<UserCourseLibraryManage> deleteList = list.stream().filter(item -> !finalOriginSaveList.contains(item)).collect(Collectors.toList());
    log.info("needAddList:size:{}, data:{}", needAddList.size(), needAddList);
    log.info("deleteList:size:{}, data:{}", deleteList.size(), deleteList);
    
    

       所以要考虑判断两个对象相等的条件,这里大家应该都知道了,就是重写equals方法,判断对象中值相等用equals方法,不用用(==)符号,(==)符号在判断对象类型时判断的是地址,这个地方需要注意的。对上面的UserCourseLibraryManage实体对象进行重写equals,在重写equals的时候,一定要注意:hashCode一般也建议重写,以保证两个对象的hash值一致,只有当对象的hash值一致时,系统才会判定这两个对象相等。重写hashcode的时候为什么用17,网上说好像Jdk就用的17,还有待考证,反正保证不要超出int范围就可以。

    /**
    * 重写equals方法
    * @param obj
    * @return
    */
    @Override
    public boolean equals(Object obj) {
    if (obj instanceof UserCourseLibraryManage) {
    if (Objects.equals(((UserCourseLibraryManage) obj).dataType, this.dataType)
    && Objects.equals(((UserCourseLibraryManage) obj).dataId, this.dataId)) {
    // System.out.println("相同对象:obj:"+obj+", this:{}"+this+"");
    return true;
    } else {
    return false;
    }
    } else {
    return super.equals(obj);
    }
    }
    
    /**
    * 重写hashcode
    * @return
    */
    @Override
    public int hashCode() {
    int newHashCode = dataType.hashCode();
    newHashCode = 17 * newHashCode + dataId.hashCode();
    return newHashCode;
    }
    
    

       这样处理了一番过后,过滤处理后的数据就是我们想要的数据,达到了目的,并且性能也肯定得到了提升,使用的java8的流处理。

    tips:上面list.stream处理的地方求差集用list自己的removeAll也是可以的。有兴趣的可以看下源码,但removeAll会将原数据集合改变。

       希望以后如果有小伙伴遇到这种问题,刚好不太了解如何处理,希望这个分享能有一定的帮助!

  • 相关阅读:
    eclipse 注释模板
    解决win7访问不了局域网共享文件
    java 执行command
    解决Unable to reach a settlement: [diffie-hellman-group1-sha1, diffie-hellman-group-exchange-sha1] and [curve25519-sha256@li
    解决java.lang.UnsupportedClassVersionError
    hadoop命令备忘
    intellij 提交代码到git
    java用代理访问
    解决 jersey javax.ws.rs.core.UriBuilder.fromUri(UriBuilder.java:119)
    解决Unable to locate Kerberos realm
  • 原文地址:https://www.cnblogs.com/xuanhaoo/p/14335365.html
Copyright © 2020-2023  润新知