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和药品数量查询出符合条件的药房列表,然后使用交集进行取值

实战:

业务层

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

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

 	@Override
    public 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 it,用于遍历当前集合。

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

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

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

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

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

你可能感兴趣的:(list,windows,数据结构)