You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算含重复元素的两个List的差集(精确匹配重复次数)

解决方案:按次数移除List中匹配的元素

嘿,这个需求我太熟了——要从list1里精准移除list2中出现的元素,而且移除次数和list2里对应元素的出现次数完全一致对吧?咱们来看看两种实用的实现方式:

方法一:基于频率统计的高效实现(适合大数据量)

这种方法用Map统计list2里每个元素的出现次数,遍历list1时精准控制移除次数,效率很高,时间复杂度是O(n+m),适合处理大列表。

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public class ListRemoveByCount {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 2));
        List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 3, 4));
        
        // 第一步:统计list2中每个元素的出现次数
        Map<Integer, Integer> elementFrequency = new HashMap<>();
        for (Integer num : list2) {
            // 用getOrDefault简化计数逻辑,不存在就默认0,然后加1
            elementFrequency.put(num, elementFrequency.getOrDefault(num, 0) + 1);
        }
        
        // 第二步:遍历list1,按次数移除元素
        // 这里必须用迭代器,不然遍历的时候删除元素会抛ConcurrentModificationException
        Iterator<Integer> iterator = list1.iterator();
        while (iterator.hasNext()) {
            Integer currentNum = iterator.next();
            // 检查当前元素在list2中还有剩余需要移除的次数
            if (elementFrequency.containsKey(currentNum) && elementFrequency.get(currentNum) > 0) {
                iterator.remove();
                // 把该元素的剩余移除次数减1
                elementFrequency.put(currentNum, elementFrequency.get(currentNum) - 1);
            }
        }
        
        System.out.println(list1); // 输出结果:[1, 2]
    }
}

思路解释:

  1. 先把list2里的元素和出现次数存在Map里,这样能快速查询每个元素需要移除多少次。
  2. 用迭代器遍历list1,普通for循环遍历删除元素会触发并发修改异常,迭代器的remove()方法是安全的。
  3. 每移除一个匹配元素,就把Map里对应的计数减1,直到计数为0就不再移除该元素。

方法二:简洁遍历实现(适合小数据量)

如果你的列表数据量不大,这种方法更简洁直观——直接遍历list2的每个元素,从list1里移除第一个匹配的元素,刚好对应list2里的出现次数。

代码示例:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class SimpleListRemove {
    public static void main(String[] args) {
        List<Integer> list1 = new ArrayList<>(Arrays.asList(1, 2, 2));
        List<Integer> list2 = new ArrayList<>(Arrays.asList(2, 3, 4));
        
        // 遍历list2的每个元素,每次从list1移除第一个匹配项
        // 遍历list2的副本是为了避免后续修改list2时出现意外,直接遍历list2也可以
        for (Integer num : new ArrayList<>(list2)) {
            list1.remove(num);
        }
        
        System.out.println(list1); // 输出结果:[1, 2]
    }
}

思路解释:

  • list1.remove(num)方法会移除list1中第一个匹配的元素,所以list2里有几个相同元素,就会从list1里移除几次,完全符合需求。比如如果list2是[2,2],那list1里的两个2都会被移除,结果就是[1]。
  • 这种方法的缺点是时间复杂度较高(每次remove()都是O(n)),但小列表完全够用,代码也更短。

内容的提问来源于stack exchange,提问作者Holipop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.20 11:44:17