2012-09-03 15 views
31

Làm cách nào để xóa các mục trùng lặp khỏi Danh sách với sự trợ giúp của ổi api?Xóa các mục trùng lặp khỏi Danh sách bằng cách sử dụng Guava

Hiện nay tôi đang sau này:

private List<T> removeDuplicate(List<T> list){ 
return new ArrayList<T>(new LinkedHashSet<T>(list)); 
} 
+5

lý do tại sao bạn muốn đi cho ổi, nếu thiết lập cơ bản thực hiện điều này? –

+0

và trong thời trang ngắn gọn như vậy, quá – Thilo

+0

@PriyankDoshi tại sao không chỉ 'HashSet'? – oldrinb

Trả lời

63

Có lẽ cách hiệu quả nhất là ImmutableSet.copyOf(list).asList(), loại bỏ trùng lặp và duy trì thứ tự lặp lại.

(Nhưng thực hiện của bạn với LinkedHashSet sẽ gần như là hiệu quả, và sẽ không ném lên trên null, trong trường hợp không chắc bạn thực sự muốn null trong bộ sưu tập của bạn.)

+3

_If_ bạn không có các phần tử rỗng;) – Xaerxess

+1

Đúng, nhưng 95% bộ sưu tập thì không. –

0

Bạn có thể thử MultiSet API ổi để loại bỏ duplicates.Just thêm danh sách của bạn làm các thiết lập và sử dụng phương pháp đếm.

MultiSet

1

Nếu bạn muốn sử dụng ổi bất cứ giá nào bạn có thể làm

return new ArrayList<T>(HashMultiSet<T>.create(list).elementSet()) 
1

Tôi thật sự không khuyên bạn sử dụng (Linked)HashMultiSet để làm nhiệm vụ đó thường được thực hiện với ArrayList(Linked)HashSet như OP đề cập ở trên - nó ít dễ đọc hơn đối với lập trình Java thông thường và (có thể) kém hiệu quả hơn.

Thay vào đó, ít nhất là sử dụng nhà thầu nhà máy tĩnh như newArrayListnewLinkedHashSet để tránh tất cả những <T> s:

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

Tuy nhiên, bạn có thể làm điều đó trong nhiều "ổi cách" - bởi avoiding nulls và sử dụng immutable collections.

Vì vậy, nếu bộ sưu tập của bạn không thể có yếu tố null, tôi muốn đề nghị sử dụng immutable set thay vì mutable and less efficient one:

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

Nó vẫn sao chép đối tượng hai lần, nên xem xét là hoàn toàn không thể thay đổi và thay đổi phương pháp chữ ký để trở lại ImmutableList:

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

Bằng cách này chỉ có một sao chép liên quan, vì ImmutableCollection.asList() trả một cái nhìn.

12

Tôi yêu Louis' answer cho sự đơn giản của nó (và vì đó là câu trả lời duy nhất không yêu cầu 2 lần lặp lại đầy đủ), nhưng thật không may trong thế giới thực, bạn thường gặp phải các tình huống khi xảy ra null. Dưới đây là một phiên bản hơi dài null-an toàn:

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

Hoặc, với hàng nhập khẩu tĩnh:

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

Tất nhiên bạn cần phải nhận thức được thực tế là tất cả null giá trị sẽ bị mất khỏi danh sách.

+3

Có một vị từ 'Predicates.notNull()' đã có sẵn. Vì vậy, kết quả cuối cùng sẽ là 'copyOf (bộ lọc (danh sách, notNull())). AsList();'. – Jonas

+0

@Jonas đúng. nhưng tại thời điểm tôi đã viết phương pháp này không tồn tại –

7

với generic vị

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; 
    } 

} 
+1

Lưu ý rằng set.add trả về true chỉ khi phần tử đã được thêm vào thực tế, do đó cuộc gọi đến set.contains là không cần thiết. – Trejkaz