如何忽略大小写检查两个列表的交集并返回无重复结果?
实现大小写不敏感的无重复列表交集
嘿,这个需求我之前做项目的时候刚好遇到过!要实现大小写不敏感、无重复的列表交集,确实不能直接用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
相关产品推荐
相关产品推荐

