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

如何忽略大小写检查两个列表的交集并返回无重复结果?

实现大小写不敏感的无重复列表交集

嘿,这个需求我之前做项目的时候刚好遇到过!要实现大小写不敏感、无重复的列表交集,确实不能直接用retainAll,因为它依赖equals()的严格匹配(String的equals是大小写敏感的)。下面给你几种实用的JDK原生实现方法,按需选就行:

方法1:用Stream API + 大小写不敏感Set(简洁直观)

这种方法代码可读性高,还能灵活选择保留哪个列表的原始大小写:

场景A:保留第二个列表的大小写形式

import java.util.*;
import java.util.stream.Collectors;

public class IntersectionExample {
    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("AbC", "def", "GHi", "abc");
        List<String> list2 = Arrays.asList("abc", "DEF", "jkl", "abc");

        // 创建大小写不敏感的Set,自动对list1去重
        Set<String> caseInsensitiveSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER);
        caseInsensitiveSet.addAll(list1);

        // 过滤list2中存在于Set的元素,再去重
        List<String> intersection = list2.stream()
                .filter(caseInsensitiveSet::contains)
                .distinct()
                .collect(Collectors.toList());

        System.out.println(intersection); // 输出: [abc, DEF]
    }
}

场景B:保留第一个列表的原始大小写形式

如果想保留list1里的原始写法(比如AbC而不是abc),可以反过来过滤:

List<String> intersection = list1.stream()
        .distinct() // 先对list1去重
        .filter(item -> list2.stream().anyMatch(item2 -> item.equalsIgnoreCase(item2)))
        .collect(Collectors.toList());

System.out.println(intersection); // 输出: [AbC, def]

方法2:用HashMap做大小写映射(性能更优)

如果你的列表数据量很大,Stream的anyMatch会带来O(n²)的时间复杂度,这时候用HashMap做小写映射,能把查找效率降到O(1):

import java.util.*;

public class IntersectionExample {
    public static void main(String[] args) {
        List<String> list1 = Arrays.asList("AbC", "def", "GHi", "abc");
        List<String> list2 = Arrays.asList("abc", "DEF", "jkl", "abc");

        // 构建list1的小写映射:key是小写字符串,value是原始字符串(自动去重)
        Map<String, String> lowerToOriginalMap = new HashMap<>();
        for (String s : list1) {
            String lowerCase = s.toLowerCase();
            lowerToOriginalMap.putIfAbsent(lowerCase, s);
        }

        // 遍历list2,筛选匹配项并去重
        List<String> result = new ArrayList<>();
        Set<String> processedKeys = new HashSet<>();
        for (String s : list2) {
            String lowerCase = s.toLowerCase();
            // 确保该小写key没被处理过,且在list1中存在
            if (lowerToOriginalMap.containsKey(lowerCase) && processedKeys.add(lowerCase)) {
                // 这里如果想保留list2的大小写,就换成 result.add(s);
                result.add(lowerToOriginalMap.get(lowerCase));
            }
        }

        System.out.println(result); // 输出: [AbC, def]
    }
}

为什么不能直接用retainAll?

Collection.retainAll()底层是通过调用元素的equals()方法来判断是否保留的,而String的equals()是严格区分大小写的,所以"AbC".equals("abc")会返回false,导致无法识别为相同元素。如果一定要用retainAll,你需要自定义一个包装类,重写equals()和hashCode()方法来忽略大小写,但这样反而比上面的方法更麻烦。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 03:57:58