前言
在之前的开发中,遇到了这样的需求:记录某个更新操作之前的数据作为日志内容,之后可以供管理员在页面上查看该日志。
思路:
- 更新接口拿入参与现在数据库该条数据逐一对比,将不同的部分取出;
- 在更新操作前取出现在数据库的该条数据,更新操作后再取出同一条数据,比较两者的异同。
经过短暂对比后,我选择方案2,理由如下:
- 前端入参未经过后端真实性校验,即万一进来的不是同一条数据呢?这样是不可靠的。
- 后端先拿参数去数据库找,如果有这条数据,那么拿出来做对比可以保证更新的是同一条数据。
要点:
- 从数据库里拿出来的一条数据其实是个实体类对象,那是否可以两个对象逐一比较属性值是否相等呢?这个不现实,因为引用类型的对象在内存中的地址肯定不同,所以对象 .equals() 的结果永远是 false;
- 既然对象不能直接比较,那么就将其先转换为一个集合后再进行 Stream 操作;
- 这里需要比较的两个集合的元素属性名相同,但是值不一定相同;
一、集合的比较
具体情况可以分为:1、是否需要得到一个新的流?2、是否只需要一个简单 boolean 结果?
我开发需求是要得到具体哪些数据不一样,所以选择返回一个新的流,只是得到一个 boolean 来判断是否相同是不够的。
1.1需要得到一个新的流
-
如果是得到一个新的流,那么推荐使用.filter() + .collect()
@Test public void testFilter(){ //第一个数组 List<ListData> list1 = new ArrayList<>(); list1.add(new ListData("测测名字11",11,"email@11")); list1.add(new ListData("测测名字22",22,"email@22")); list1.add(new ListData("测测名字33",33,"email@33")); log.info("第一个数组为:{}", list1); //第二个数组 List<ListData> list2 = new ArrayList<>(); list2.add(new ListData("测测名字111",111,"email@11")); list2.add(new ListData("测测名字22",22,"email@22")); list2.add(new ListData("测测名字33",33,"email@33")); log.info("第二个数组为:{}", list2); //返回一个新的结果数组 List<ListData> resultList = list1.stream() //最外层的filter里是条件,这个条件需要返回一个boolean:符合条件返回true,不符合条件返回false .filter(p1 -> list2.stream() //这个filter也是条件:判断两个数组里名字和年龄是否都相等,符合条件返回true,不符合条件返回false .filter(p2 -> p2.getName().equals(p1.getName()) && p2.getAge().equals(p1.getAge())) //如有内容则返回流中的第一条记录,其它情况都返回空 .findFirst().orElse(null) //这个是最外层的filter的断言 == null) //将上一步流处理的的结果,收集成一个新的集合 .collect(Collectors.toList()); log.info("经过 Stream 流处理后输出的结果数组为: {}", resultList); }结合.filter() + noneMatch() 其实也与上面的语句效果相同:
List<ListData> resultList = list1.stream() .filter(p1 -> list2.stream() //这个 noneMatch 也是条件:判断两个数组里名字和年龄是否都相等,符合条件返回true,不符合条件返回false .noneMatch(p2 -> p2.getName().equals(p1.getName()) && p2.getAge().equals(p1.getAge()))) .collect(Collectors.toList()); log.info("经过 Stream 流处理后输出的结果数组为: {}", resultList);结合 filter() + contains() 方法( 其中 contains() 方法的使用详见 1.2 小节的注意事项),与以上的效果也一样:
List<ListData> resultList = list1.stream().filter(p1 -> !list2.contains(p1)).collect(Collectors.toList()); log.info("经过 Stream 流处理后输出的结果数组为: {}", resultList);下面是以上代码的运行结果如图 1 所示: