34

How can we remove duplicates from List with the help of Guava api?

Currently I am following this:

private List<T> removeDuplicate(List<T> list){
return new ArrayList<T>(new LinkedHashSet<T>(list));
}
Priyank Doshi
  • 12,895
  • 18
  • 59
  • 82

6 Answers6

70

Probably the most efficient way is ImmutableSet.copyOf(list).asList(), which eliminates duplicates and preserves iteration order.

(But your implementation with LinkedHashSet would be nearly as efficient, and wouldn't throw up on nulls, in the unlikely event you actually wanted nulls in your collection.)

Louis Wasserman
  • 191,574
  • 25
  • 345
  • 413
12

I love Louis' answer for the simplicity of it (and because it's the only answer that doesn't require 2 full iterations), but unfortunately in the real world, you often encounter situations where null does occur. Here's a slightly longer null-safe version:

ImmutableSet.copyOf(
    Iterables.filter(
        list, Predicates.not(Predicates.isNull()))).asList();

Or, with static imports:

copyOf(filter(list, not(isNull()))).asList();

Of course you need to be aware of the fact that all null Values will be lost from the List.

Community
  • 1
  • 1
Sean Patrick Floyd
  • 292,901
  • 67
  • 465
  • 588
7

with generic predicate

class DuplicateRemover<T> implements Predicate<T> {

    private final Set<T> set = new HashSet<>();

    @Override
    public boolean apply(T input) {

        boolean flag = set.contains(input);

        if (!flag) {
            set.add(input);
        }

        return !flag;
    }

}
jeton
  • 841
  • 12
  • 15
  • 2
    Note that set.add returns true only if the element was actually added, so the call to set.contains is unnecessary. – Hakanai May 01 '17 at 06:14
1

If you wanna use Guava at any price you can do

return new ArrayList<T>(HashMultiSet<T>.create(list).elementSet())
halex
  • 16,253
  • 5
  • 58
  • 67
1

I really don't recommend using (Linked)HashMultiSet to do task which is usually done with ArrayList and (Linked)HashSet like OP mentioned above - it's less readable for regular Java programmer and (probably) less efficient.

Instead, at least use static factory constructors like newArrayList and newLinkedHashSet to avoid all these <T>s:

private static <T> List<T> removeDuplicate(final List<T> list) {
  return Lists.newArrayList(Sets.newLinkedHashSet(list));
}

However, you can do it in more "Guava way" - by avoiding nulls and using immutable collections.

So if your collection cannot have null elements, I'd suggest using immutable set instead of mutable and less efficient one:

private static <T> List<T> removeDuplicate(final List<T> list) {
  return Lists.newArrayList(ImmutableSet.copyOf(list));
}

It's still copying objects twice, so consider being fully-immutable and changing method signature to return ImmutableList:

private static <T> ImmutableList<T> removeDuplicate(final List<T> list) {
  return ImmutableSet.copyOf(list).asList();
}

This way there is only one copying involved, because ImmutableCollection.asList() returns a view.

Grzegorz Rożniecki
  • 27,415
  • 11
  • 90
  • 112
0

You can try Guava's MultiSet API to remove duplicates.Just add your list do the set and use the count method.

MultiSet

UVM
  • 9,776
  • 6
  • 41
  • 66