Java 8中使用Lambda函数忽略大小写去除ArrayList<String>重复项
Hey there, I get exactly what you're dealing with here—standard Java tools fall short when you need to ignore case while removing duplicates from a String ArrayList. Let's break down why the usual approaches don't work first, then jump into solid solutions.
First, you're totally right about distinct(): it uses the default equals() method for Strings, which checks for exact case matches. So "Luke" and "luke" get treated as completely different elements. And regular Maps (like HashMap) don't help either because their keys are case-sensitive—adding "Luke" then "luke" just creates two separate entries.
Solution 1: Keep Original Order & Preserve First Occurrence's Case
If you want to maintain the order of your original list and keep the casing of the first occurrence of each duplicate, this Stream-based approach works great:
import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.Set; import java.util.stream.Collectors; public class CaseInsensitiveDuplicateRemover { public static void main(String[] args) { List<String> originalList = Arrays.asList("Luke", "luke", "Anna", "anna", "Bob", "bob", "Luke"); Set<String> seenLowerCase = new HashSet<>(); List<String> uniqueList = originalList.stream() .filter(s -> seenLowerCase.add(s.toLowerCase())) .collect(Collectors.toList()); System.out.println(uniqueList); // Output: [Luke, Anna, Bob] } }
How this works: We use a HashSet to track the lowercase version of every string we've already processed. The add() method returns false if the lowercase string is already in the set, so the filter drops any subsequent case variants. This keeps your original order intact and retains the first occurrence's original casing.
Solution 2: Ignore Order (Uses Sorted Output)
If you don't care about preserving the original order, you can use a TreeSet with a case-insensitive comparator. This automatically removes duplicates and sorts the result:
import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.TreeSet; public class CaseInsensitiveDuplicateRemover { public static void main(String[] args) { List<String> originalList = Arrays.asList("Luke", "luke", "Anna", "anna", "Bob"); TreeSet<String> caseInsensitiveSet = new TreeSet<>(String.CASE_INSENSITIVE_ORDER); caseInsensitiveSet.addAll(originalList); List<String> uniqueList = new ArrayList<>(caseInsensitiveSet); System.out.println(uniqueList); // Output: [Anna, Bob, Luke] } }
Solution 3: Using HashMap (Alternative to Stream)
If you prefer a non-stream approach, a HashMap can do the job too—we just use lowercase strings as keys to track duplicates, while storing the original string as the value:
import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; public class CaseInsensitiveDuplicateRemover { public static void main(String[] args) { List<String> originalList = Arrays.asList("Luke", "luke", "Anna", "anna", "Bob"); Map<String, String> uniqueMap = new HashMap<>(); for (String s : originalList) { String lowerKey = s.toLowerCase(); if (!uniqueMap.containsKey(lowerKey)) { uniqueMap.put(lowerKey, s); } } List<String> uniqueList = new ArrayList<>(uniqueMap.values()); System.out.println(uniqueList); // Output: [Luke, Anna, Bob] } }
This also preserves the first occurrence's casing and order (since HashMap maintains insertion order as of Java 8).
Pick the solution that fits your needs best—whether order matters, or if sorted output is acceptable.
内容的提问来源于stack exchange,提问作者Sachin Verma

