List中交集的使用

前言

新增了一个需求,需要将所有药品和对应数量库存的药房查询出来,要求:‘所有药品该药房都要有,并且库存大于购药数量’;

这就得考虑一个问题,有的药房有该药品,有的药房没有该药品,这该如何处理?

因为每个药品可能这个药房有,另一个药房没有,所以我们需要使用数学中的交集,将所有包含全部药品并且库存大于购药数量的药房列表取出来。

交集

对于两个给定集合A、B,由属于A又属于B的所有元素构成的集合,叫做A和B的交集。
记作: A∩B 读作“A交B”
例:A={1,2,3,4,5},B={3,4,5,6,8},A∩B={3,4,5}

白话:就是A中有的元素,B中也有的元素,将它们取出来,组成新的集合

我们通过药品id和药品数量查询出符合条件的药房列表,然后使用交集进行取值

实战:

业务层

// 解释:如果只有一个药品的话,就直接查询出所有符合条件的药房列表,然后添加到最终的药房列表中;

// 如果是多个药品的话,需要通过遍历一个药品一个药品的查询出所有符合条件的药房列表,然后通过交集一个一个取出相同的元素,直到最后一次遍历,将取出的交集最终结果添加到最终的药房列表中;

 	@Overridepublic String findPharmacyList(List<Map<String, Object>> mapList) {// 这两个 HashSet 是为了去重准备的Set<Map<String, Object>> retainAll1 = new HashSet<>();Set<Map<String, Object>> retainAll2 = new HashSet<>();List<Map<String, Object>> pharmacyList = new ArrayList<>();if (mapList.size() == 1) { // 单个药品的话,只要查找出所有符合条件的药房就可以了,然后将查询出来的药房列表通过addAll方法添加到 pharmacyList 列表中pharmacyList.addAll(drugOrderRepository.findPharmacyList((Integer) mapList.get(0).get("drugId"), (Integer) mapList.get(0).get("drugNumber")).stream().map(pharmacy -> {Map<String, Object> map = new HashMap<>();map.put("pharmacyName", pharmacy.get("pharmacyName"));map.put("pharmacyAddress", pharmacy.get("pharmacyAddress"));map.put("pharmacyId", pharmacy.get("pharmacyId"));return map;}).collect(Collectors.toList()));} else { // 多个药品的话,需要通过 for 循环将每个药品对应的药房列表遍历出来,然后通过交集进行判断,将所有药品都有的药房和满足库存大于购药数的药房列表取出来,添加到 pharmacyList 列表中for (Map<String, Object> hashMap : mapList) {List<Map<String, Object>> pharmacyList1 = drugOrderRepository.findPharmacyList((Integer) hashMap.get("drugId"), (Integer) mapList.get(0).get("drugNumber"));Set<Map<String, Object>> currentSet = (hashMap.get("drugId").equals(mapList.get(0).get("drugId"))) ? retainAll1 : retainAll2;pharmacyList1.forEach(pharmacy -> {Map<String, Object> map = new HashMap<>();map.put("pharmacyName", pharmacy.get("pharmacyName"));map.put("pharmacyAddress", pharmacy.get("pharmacyAddress"));map.put("pharmacyId", pharmacy.get("pharmacyId"));currentSet.add(map);});// 必须进行判断,只有 retainAll1 和 retainAll2 这两个函数里面都有值才能进行交集取值if (!retainAll1.isEmpty() && !retainAll2.isEmpty()) {// 通过 retainAll1.retainAll(retainAll2); 进行交集取值,取出两个函数都有的值,retainAll1 就是交集的最终结果retainAll1.retainAll(retainAll2);// 必须要 new 一下,不然之前的数据会累加,会将两个列表的值合并,造成最终结果错误retainAll2 = new HashSet<>();// 必须到最后一次遍历才进入到对 pharmacyList 列表使用 addAll 进行数据的添加,将最终结果添加到 pharmacyList 列表中,不然会造成最终数据不准确的问题if (mapList.get(mapList.size() - 1).get("drugId").equals(hashMap.get("drugId"))) {pharmacyList = new ArrayList<>();pharmacyList.addAll(retainAll1.stream().map(retain -> {Map<String, Object> map = new HashMap<>();map.put("pharmacyName", retain.get("pharmacyName"));map.put("pharmacyAddress", retain.get("pharmacyAddress"));map.put("pharmacyId", retain.get("pharmacyId"));return map;}).collect(Collectors.toList()));}}}}return RespBean.success("成功",pharmacyList);}

List交集源码解释

 public boolean retainAll(Collection<?> c) {Objects.requireNonNull(c);boolean modified = false;Iterator<E> it = iterator();while (it.hasNext()) {if (!c.contains(it.next())) {it.remove();modified = true;}}return modified;}
  1. 首先,retainAll(Collection<?> c)方法是一个公共方法,返回一个布尔值,表示是否对当前集合进行了修改。

  2. 方法的参数是一个Collection<?> c,它是另一个集合,用于与当前集合进行比较和操作。注意,这里使用了Java的泛型,表示c可以是任何类型的集合。

  3. 方法中首先使用Objects.requireNonNull(c)来确保传入的集合c不为null,如果为null,则抛出NullPointerException

  4. 然后,声明一个布尔变量modified,用于记录当前集合是否有被修改的操作。

  5. 创建一个迭代器Iterator<E> it,用于遍历当前集合。

  6. 使用while (it.hasNext())循环遍历当前集合的每个元素。

  7. 在循环内部,使用if (!c.contains(it.next()))来判断集合c是否包含当前迭代到的元素。如果不包含,则执行以下操作:

    a. 调用it.remove()方法来移除当前迭代到的元素。

    b. 将modified设置为true,表示当前集合被修改过。

  8. 最后,循环结束后,返回modified,表示在遍历过程中是否对当前集合进行了修改。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/12195.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端常用的条件限制方法小笔记

手机号的正则表达式(以1开头的11位数字) function checkPhone(){ var phone document.getElementById(phone).value;if(!(/^1[3456789]\d{9}$/.test(phone))){ alert("手机号码有误&#xff0c;请重填"); return false; } }限制输入大于0且最小值要小于最大值 c…

php项目内存飚高处理与优化

公司服务器最近内存占用超过阈值一直报警 经过排查,内存占用很多&#xff0c;剩余很少 free -m 排查代码无太多冗余和缓存 最后和运维一起排查&#xff0c;发现宝塔安装后带的gitlab的进程很吃内存&#xff0c;赶紧停用&#xff0c;并卸载无用的软件 最后内存降下来了

16.Netty源码之ChannelPipeline

highlight: arduino-light 服务编排层:ChannelPipeline协调ChannelHandlerHandler EventLoop可以说是 Netty 的调度中心&#xff0c;负责监听多种事件类型&#xff1a;I/O 事件、信号事件、定时事件等&#xff0c;然而实际的业务处理逻辑则是由 ChannelPipeline 中所定义的 Cha…

Vue-Router基本使用

1 安装&#xff1a; vue2项目要安装vue-router3版本 npm i vue-router3 2 src下创建router目录&#xff0c;router文件夹下创建index.js 在vue.config.js中 配置src路径别名 3 在main.js中引入 4 在app.vue中配置 5 即可看到内容

Elasticsearch 常用 HTTP 接口

本文记录工作中常用的关于 Elasticsearch 的 HTTP 接口&#xff0c;以作备用&#xff0c;读者也可以参考&#xff0c;会持续补充更新。开发环境基于 Elasticsearch v5.6.8、v1.7.5、v2.x。 集群状态 集群信息 1 2 3 4 5 6 7http://localhost:9200/_cluster/stats?pretty http…

okhttp原理分析

工程目录图 请点击下面工程名称&#xff0c;跳转到代码的仓库页面&#xff0c;将工程 下载下来 Demo Code 里有详细的注释 01okhttp module里 包含的设计模式&#xff1a;建造者设计模式、责任链设计模式 CustomInject 演示自定义注解 代码&#xff1a;okhttp原理分析、Andro…

掌握Python的X篇_13_Python条件语句实例:判断闰年、成绩评定

前面学习了条件语句以及调试的基本技巧&#xff0c;本篇介绍两个与条件语句有关的实例&#xff0c;对前面的知识又深刻认识。 文章目录 1. 判断闰年1.1 版本11.2 版本21.3 一行代码太长的处理方法 2. 根据成绩评级 1. 判断闰年 用户输入年份&#xff0c;判断该年份是否为闰年…

Perl:命令行参数的处理

相关阅读 Perl&#xff1a;正则表达式 Perl&#xff1a;什么是其特有的autovivafacation性质&#xff1f; Perl&#xff1a;匿名数组嵌套的解引用相关问题 命令行参数是shell和perl交互的一个重要媒介&#xff0c;本文介绍了如何在Perl中对命令行参数进行处理。 首先我们给出…

esp32_arduino的开发库安装笔记

1.1 Arduino软件下载与安装 Arduino官网下载地址&#xff1a;https://www.arduino.cc/en/software。 1.2在线安装 选择文件 - 首选项。 在附加开发板管理器网址中添加以下链接中的一个。 (1)Stable release link: https://raw.githubusercontent.com/espressif/arduino-es…

【Linux后端服务器开发】MAC地址与其他重要协议

目录 一、以太网 二、MAC地址 三、MTU 四、ARP协议 五、DNS系统 六、ICMP协议 七、NAT技术 八、代理服务器 一、以太网 “以太网”不是一种具体的网路&#xff0c;而是一种技术标准&#xff1a;既包含了数据链路层的内容&#xff0c;也包含了一些物理层的内容&#xf…

【STM32MP1系列】DDR内存测试用例

DDRDDR内存测试 一、uboot下测试DDR内存二、Linux内核下测试DDR内存1、使用memtester测试DDR内存2、使用stressapptest测试DDR内存三、Buildroot中构建memtester软件包四、搭建stressapptest软件包五、注意事项一、uboot下测试DDR内存 输入bdinfo查看DDR起始地址以及大小: b…

【ARM Coresight 系列文章 10.3 - ARM Coresight STM 寄存器介绍 及STM DMA 传输介绍】

文章目录 STM Register summarySTM DMA 相关的寄存器DMA TransferBurst requestSingle and burst request STM Register summary STM 的寄存器主要可以分为以下几类&#xff1a; STM DMA 相关的&#xff1b;STM HW Trigger 相关的&#xff1b;系统控制及状态寄存器&#xff1…

Linux系统中的SQL语句

本节主要学习&#xff0c;SQL语句的语句类型&#xff0c;数据库操作&#xff0c;数据表操作&#xff0c;和数据操作等。 文章目录 一、SQL语句类型 DDL DML DCL DQL 二、数据库操作 1.查看 2.创建 默认字符集 指定字符集 3.进入 4.删除 5.更改 库名称 字符集 6…

用python通过http实现文件传输,分为发送端和接收端

要使用Python通过HTTP实现文件传输&#xff0c;可以使用Python的 requests 库来发送和接收HTTP请求。以下是一个示例代码&#xff0c;其中包括发送端和接收端的实现。 发送端&#xff1a; import requestsdef send_file(file_path, url):with open(file_path, rb) as file:re…

Safetensors,高效安全易用的深度学习新工具

大家好&#xff0c;本文将介绍一种为深度学习应用提供速度、效率、跨平台兼容性、用户友好性和安全性的新工具。 Safetensors简介 Hugging Face开发了一种名为Safetensors的新序列化格式&#xff0c;旨在简化和精简大型复杂张量的存储和加载。张量是深度学习中使用的主要数据…

Cypress 上传 pdf 变空白页问题

在使用cypress 上传文件时&#xff0c;上传正常&#xff0c;但是&#xff0c;pdf一直空白的&#xff0c;翻边了资料也没找到原因。最后在一个不起眼的地方发现了问题所在。 错误的代码&#xff1a; cy.fixture(CBKS.pdf).as(uploadFile)cy.get(.el-upload-dragger).selectFile…

借助 Mybatis 的动态 SQL 解决传参不确定问题

在上一篇的&#xff1a;Mybatis 操作数据库的基本 CRUD 以及查询操作详析_糊糊涂涂的博客-CSDN博客中介绍了Mybatis使用固定SQL语句操作数据&#xff0c;本篇介绍 Mybatis 一个强大的特性&#xff1a;动态SQL。 动态 SQL 解决什么问题&#xff1f; 那当我们要执行的业务逻辑有…

【Nodejs】Node.js开发环境安装

1.版本介绍 在命令窗口中输入 node -v 可以查看版本 0.x 完全不技术 ES64.x 部分支持 ES6 特性5.x 部分支持ES6特性&#xff08;比4.x多些&#xff09;&#xff0c;属于过渡产品&#xff0c;现在来说应该没有什么理由去用这个了6.x 支持98%的 ES6 特性8.x 支持 ES6 特性 2.No…

vue3如何封装接口

&#x1f642;博主&#xff1a;锅盖哒 &#x1f642;文章核心&#xff1a;如何封装接口 目录 前言 1.首先&#xff0c;安装并导入axios库。你可以使用npm或yarn来安装&#xff1a; 2.创建一个api.js文件来管理接口封装&#xff1a; 3.在Vue组件中使用封装的接口&#xff1…

Andrid进阶之回调方法

回调在android开发中必不可少&#xff0c;也是比较常见的&#xff0c;比如控件的点击事件&#xff0c;我们自定义回调基本就是在创建一个方法的时候能够及时拿到对应的信息 Kotlin写法&#xff1a; private var mOnListener: OnMListener? nullinterface OnMListener {fun g…