1

I need to remove duplicates from an ArrayList of String irrespective of cases. for eq:

List list = Lists.newArrayList("Luke","luke");// it's guava's method
list.stream().distinct();

distinct() above wont do any help as it works on equals method which will return false. Is there any other way that can do something like:

list.stream().distinct((a,b)->a.equalsIgnoreCase(b)).collect(..);

Update: It might be different from possible duplicate because the possible duplicate's answers do show how to use distinct() with property using a map. But a map that contains "Luke" will not return true if added "luke" and hence those answers wont work for this problem.

Sachin Verma
  • 3,712
  • 10
  • 41
  • 74

2 Answers2

1

Here is one way to do it. I assumed that the duplicate items do not need to be next to each other, so I had to use a HashSet to keep it O(n). Also, had to agree on a case (went with lower case).

public static void main(String[] args) {
    List<String> list = Arrays.asList("Luke", "tony", "Tony", "luke");
    Set<String> set = new HashSet<>();
    list.stream().map(s -> s.toLowerCase()).filter(s -> !set.contains(s)).forEach(set::add);
    System.out.println(set);
}
Jose Martinez
  • 11,452
  • 7
  • 53
  • 68
0

Here's a possibility using a local class:

public List<String> yourFunction(List<String> list) {
    class IgnoringCase {
        String wrapped;
        public IgnoringCase(String w) { wrapped = w; }
        public boolean equals(Object o) {
            if (o instanceof IgnoringCase) {
                IgnoringCase other = (IgnoringCase) o;
                return wrapped.equalsIgnoreCase(other.wrapped);
            } return false;
        }
    }
    return list.stream()
        .map(IgnoringCase::new) // enable alternative equals
        .distinct()
        .map(i -> i.wrapped) // map back to String
        .collect(toList());
}

Obviously, there's no need to make the class local and you can use a static nested or top level class if you like it better.

daniu
  • 14,137
  • 4
  • 32
  • 53