Java中检查列表是否包含另一列表全部元素(含重复元素校验)
带元素频次检查的列表包含判断方案
嘿,这个问题我之前也碰到过!普通的List.containsAll()方法只会验证每个元素是否存在于目标列表中,完全不考虑元素的出现次数——所以像你说的{a,a,d,e}和{a,d,e}这种情况,它会错误地返回true,但咱们要的是false,因为目标列表里的a数量不够覆盖源列表的。
下面给你两种可行的实现方式:
方法一:用HashMap手动统计频次(纯JDK,无需第三方库)
这是最通用的方式,完全依赖JDK自带的类就能实现:
import java.util.HashMap; import java.util.List; import java.util.Map; public class ContainmentChecker { public static boolean isContainedWithFrequency(List<Character> source, List<Character> target) { // 统计源列表中每个字符的出现次数 Map<Character, Integer> sourceCounts = new HashMap<>(); for (char c : source) { sourceCounts.put(c, sourceCounts.getOrDefault(c, 0) + 1); } // 统计目标列表中每个字符的出现次数 Map<Character, Integer> targetCounts = new HashMap<>(); for (char c : target) { targetCounts.put(c, targetCounts.getOrDefault(c, 0) + 1); } // 逐一验证:源列表的每个字符,目标列表的数量都要足够 for (Map.Entry<Character, Integer> entry : sourceCounts.entrySet()) { char charToCheck = entry.getKey(); int requiredCount = entry.getValue(); // 如果目标里没有这个字符,或者数量不够,直接返回false if (!targetCounts.containsKey(charToCheck) || targetCounts.get(charToCheck) < requiredCount) { return false; } } return true; } public static void main(String[] args) { List<Character> listA = List.of('a', 'a', 'd', 'e'); List<Character> listB = List.of('a', 'd', 'e'); System.out.println(isContainedWithFrequency(listA, listB)); // 输出false,符合你的预期 } }
方法二:用Guava的Multiset(简洁高效,适合已引入Guava的项目)
如果你的项目已经在使用Guava库,那Multiset就是为这种带计数的集合场景设计的,代码会简洁很多:
import com.google.common.collect.HashMultiset; import com.google.common.collect.Multiset; import java.util.List; public class MultisetContainmentChecker { public static boolean isContainedWithFrequency(List<Character> source, List<Character> target) { Multiset<Character> sourceMultiset = HashMultiset.create(source); Multiset<Character> targetMultiset = HashMultiset.create(target); // 遍历源集合的每个元素,检查目标集合的计数是否足够 for (Multiset.Entry<Character> entry : sourceMultiset.entrySet()) { if (targetMultiset.count(entry.getElement()) < entry.getCount()) { return false; } } return true; } public static void main(String[] args) { List<Character> listA = List.of('a', 'a', 'd', 'e'); List<Character> listB = List.of('a', 'd', 'e'); System.out.println(isContainedWithFrequency(listA, listB)); // 输出false } }
额外说明
- 这两种方法的核心逻辑都是对比元素的出现频次,确保源列表的每个元素的次数都不超过目标列表的对应次数。
- 如果你的列表里可能出现
null字符,记得在统计的时候加个空指针判断(比如if (c == null) { ... }),不过你的例子里都是普通字符,应该不需要。
内容的提问来源于stack exchange,提问作者user8037780
相关产品推荐
相关产品推荐

