集合List和Set使用

问题

多线程 处理数据,每个子线程返回的结果都一样。理论上返回结果集应该不一样。

排查

检查线程中处理逻辑是否有问题,InsuranceDetailCallable中call()方法主体逻辑正确,可能存在的传到每个子线程中的List insuranceDetails数据是一样的,导致每个线程的数据结果都一样。

/*** 数据处理 operate_type link_id*/
private class InsuranceDetailCallable implements Callable<Set<Long>> {private CountDownLatch countDownLatch;private List<FinalStatementInsuranceDetail> insuranceDetails;public InsuranceDetailCallable(CountDownLatch countDownLatch,List<FinalStatementInsuranceDetail> insuranceDetails) {this.countDownLatch = countDownLatch;this.insuranceDetails = insuranceDetails;}@Overridepublic Set<Long> call() {Set<Long> result = new HashSet<>();try {//代码省略} catch (Exception e) {System.out.println("子线程异常:" + e.getMessage());} finally {countDownLatch.countDown();}return result;}
}

父线程中将获取到的list数据根据statementId字段进行分组得到Map集合,接着将Map中的key进行分组得到List<List>组,子线程分别对这些group中集合进行处理数据。问题出现在代码

List<List<Long>> groupList = Stream.iterate(0, n -> n + 1).limit(set.size()).parallel().map(a -> set.stream().skip((long) a * finalSize).limit(finalSize)      .parallel().collect(Collectors.toList())).filter(CollUtil::isNotEmpty).collect(Collectors.toList());

处理的集合Set是无序的,并行处理分组数据,导致分组完的groupList中数据List部分数据一样,子线程中处理的数据也一样。List是有序的,将Set转换成List,可以解决这个问题。

/*** 修改前父线程代码*/
public void testMaintainNormalOperateType() {//获取还未处理的数据List<FinalStatementInsuranceDetail> insuranceDetailList = insuranceDetailService.listOperateTypeIsNull();if (CollUtil.isEmpty(insuranceDetailList)) {return;}Map<Long, List<FinalStatementInsuranceDetail>> mapList = insuranceDetailList.stream().collect(Collectors.groupingBy(FinalStatementInsuranceDetail::getStatementId));Set<Long> set = mapList.keySet();int size = set.size() / 100;if (size == 0) {size = set.size();}int finalSize = size;List<List<Long>> groupList = Stream.iterate(0, n -> n + 1).limit(list.size()).parallel().map(a -> set.stream().skip((long) a * finalSize).limit(finalSize).parallel().collect(Collectors.toList())).filter(CollUtil::isNotEmpty).collect(Collectors.toList());
}

修改后的父线程代码

public void testMaintainNormalOperateType() {long start = System.currentTimeMillis();List<FinalStatementInsuranceDetail> insuranceDetailList = insuranceDetailService.listOperateTypeIsNull(true);if (CollUtil.isEmpty(insuranceDetailList)) {return;}Map<Long, List<FinalStatementInsuranceDetail>> mapList = insuranceDetailList.stream().collect(Collectors.groupingBy(FinalStatementInsuranceDetail::getStatementId));List<Long> list = new ArrayList<>(mapList.keySet());try {int size = list.size() / 100;if (size == 0) {size = list.size();}int finalSize = size;List<List<Long>> groupList = Stream.iterate(0, n -> n + 1).limit(list.size()).parallel().map(a -> list.stream().skip((long) a * finalSize).limit(finalSize).parallel().collect(Collectors.toList())).filter(CollUtil::isNotEmpty).collect(Collectors.toList());ExecutorService executorService = Executors.newFixedThreadPool(groupList.size());CountDownLatch countDownLatch = new CountDownLatch(groupList.size());List<Future<Set<Long>>> futureList = new ArrayList<>();for (List<Long> statementIdList : groupList) {List<FinalStatementInsuranceDetail> insuranceDetails = new ArrayList<>();for (Long statementId : statementIdList) {insuranceDetails.addAll(mapList.getOrDefault(statementId, new ArrayList<>()));}InsuranceDetailCallable callable = new InsuranceDetailCallable(countDownLatch, insuranceDetails);Future<Set<Long>> future = executorService.submit(callable);futureList.add(future);}executorService.shutdown();for (Future<Set<Long>> future : futureList) {Set<Long> setLong = future.get();System.out.println("输出:" + setLong.size() + " " + JSONObject.toJSONString(setLong));}} catch (Exception e) {System.out.println("父线程异常:" + e.getMessage());}long end = System.currentTimeMillis();System.out.println("耗时 = " + (end - start) / 1000);
}

另外一种方式使用apache.commons夹包ListUtils.partition(List list, int size)方法

<!--对应maven依赖 -->
<dependency><groupId>org.apache.commons</groupId><artifactId>commons-collections4</artifactId><version>4.1</version>
</dependency>

总结

List是有序的,不唯一;Set无序,数据唯一。

lambda分组集合中list和set区别相关推荐

  1. JAVA 8 lambda 表达式实现按某个属性值查找对象集合中符合条件的对象

    转载自:https://www.cnblogs.com/lindsayYang/p/9843599.html JAVA 8 lambda 表达式实现按某个属性值查找对象集合中符合条件的对象 当前的需求 ...

  2. 【整理】Python中的re.search和re.findall之间的区别和联系 + re.finall中带命名的组,不带命名的组,非捕获的组,没有分组四种类型之间的区别

    之前自己曾被搞晕过很多次. 后来使用这些函数次数多了之后,终于比较清楚的弄懂了两者之间的区别和关系了. 尤其是一些细节方面的注意事项了. 在看下面的总结和代码之前,请先确保你对如下基本概念已经有所了解 ...

  3. Java的lambda实战(二)集合中的lambda

    文章目录 1.背景 2.集合中的lambda 2.1.stream 2.2.操作集合 3.总结 1.背景 本章梳理一下常见的集合使用. 集合中lambda使用概念:https://blog.csdn. ...

  4. Map集合中value()方法与keySet()、entrySet()区别 ——转载

    为什么80%的码农都做不了架构师?>>>    在Map集合中 values():方法是获取集合中的所有的值----没有键,没有对应关系, KeySet(): 将Map中所有的键存入 ...

  5. 详解在group by分组查询中where 和 having的用法和区别。

    我地都知道sql 中 where 和 having 都是用来筛选条件的关键字. 而且having 一般和group by 一齐使用,   但是where 也可以用group by 一齐使用的. 下面用 ...

  6. 技术图文:如何通过 LINQ 查找集合中的重复数据?

    背景 在前几天介绍的 如何利用C#实现Huffman编码? 的图文中有以下代码. private List<HuffmanTreeNode> CreateInitForest(string ...

  7. 如何在lambda表达式域中使用局部变量?

    如何在lambda表达式域中使用局部变量? Lambda 表达式是 JDK8 的一个新特性,可以取代大部分的匿名内部类,写出更优雅的 Java 代码,尤其在集合的遍历和其他集合操作中,可以极大地优化代 ...

  8. JAVA 中equals()与==的区别

    原文地址:http://www.chineselinuxuniversity.net/articles/29594.shtml 值类型是存储在内存中的堆栈(以后简称栈),而引用类型的变量在栈中仅仅是存 ...

  9. android 集合 内存泄漏,Android内存泄漏第二课--------(集合中对象没清理造成的内存泄漏 )...

    一.我们通常把一些对象的引用加入到了集合容器(比如ArrayList)中,当我们不需要该对象时,并没有把它的引用从集合中清理掉,这样这个集合就会越来越大.如果这个集合是static的话,那情况就更严重 ...

最新文章

  1. python集合的运算、不使用有的运算符_无序的集合:Python中的数学集合运算
  2. .Net Core2.1 秒杀项目一步步实现CI/CD(Centos7)系列二:k8s高可用集群搭建总结以及部署API到k8s...
  3. Spring Boot项目CentOS域名的绑定
  4. React-概念和基本使用
  5. ukey网络连接异常_Ukey的各种操作,你知道吗?
  6. 关于无线网卡驱动安装正确,但灯不亮的问题
  7. outlook 2016 添加126邮箱教程
  8. 程序识别验证码图片(一)
  9. 处理7z格式的001 002 文件
  10. Access key id should not be null or empty.
  11. android和ios测试环境搭建,iOS自动化测试环境搭建
  12. 机器学习中的数学——单位矩阵和逆矩阵
  13. 144显示器只有60_DIY老司机:吃鸡显示器非得用144Hz,60Hz就不行?
  14. 「颜值即正义」那些管UI的妹子要来的网站啦
  15. Android设置应用程序默认语言
  16. SMOS土壤水分数据下载教程
  17. Postman使用技巧之Authorization使用
  18. 基于计组实验软件CMStudio设计一种简单同或运算指令系统
  19. AutoCAD 出现“安全系统(软件锁许可管理器)不起作用或未正确安装”的解决方法
  20. Dubbo 与 Feign 的区别

热门文章

  1. 【架构】需求决定架构 —— 萌Mark的架构升级之路
  2. laravel 实现app支付宝退款
  3. 《未来简史(下)》万维钢解读
  4. LayoutTransiton实现简单的录制按钮
  5. Nginx反向代理与负载均衡应用实践(二)
  6. tensorflow中squeeze与expand_dims
  7. 20200903-03-Hadoop运行模式之本地运行模式伪分布式运行模式
  8. 深蓝算法反演AOD入门记录(一)
  9. html 自动生产,HTML5 Three.js 3D人偶玩具自动化生产车间动画
  10. 《国史通鉴》历代一句话概括总结+大脉络记历史~~