前言
新增了一个需求,需要将所有药品和对应数量库存的药房查询出来,要求:‘所有药品该药房都要有,并且库存大于购药数量’;
这就得考虑一个问题,有的药房有该药品,有的药房没有该药品,这该如何处理?
因为每个药品可能这个药房有,另一个药房没有,所以我们需要使用数学中的交集,将所有包含全部药品并且库存大于购药数量的药房列表取出来。
交集
对于两个给定集合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;}
-
首先,
retainAll(Collection<?> c)
方法是一个公共方法,返回一个布尔值,表示是否对当前集合进行了修改。 -
方法的参数是一个
Collection<?> c
,它是另一个集合,用于与当前集合进行比较和操作。注意,这里使用了Java的泛型,表示c
可以是任何类型的集合。 -
方法中首先使用
Objects.requireNonNull(c)
来确保传入的集合c
不为null,如果为null,则抛出NullPointerException
。 -
然后,声明一个布尔变量
modified
,用于记录当前集合是否有被修改的操作。 -
创建一个迭代器
Iterator<E> it
,用于遍历当前集合。 -
使用
while (it.hasNext())
循环遍历当前集合的每个元素。 -
在循环内部,使用
if (!c.contains(it.next()))
来判断集合c
是否包含当前迭代到的元素。如果不包含,则执行以下操作:a. 调用
it.remove()
方法来移除当前迭代到的元素。b. 将
modified
设置为true
,表示当前集合被修改过。 -
最后,循环结束后,返回
modified
,表示在遍历过程中是否对当前集合进行了修改。