2010-02-10 49 views
33

Tôi đọc dữ liệu từ một tập tin văn bản, do đó có thể là:Lưu một danh sách các Strings duy nhất trong ArrayList

 
John 
Mary 
John 
Leeds 

bây giờ tôi cần phải nhận được 3 yếu tố duy nhất trong ArrayList, bởi vì chỉ có 3 độc đáo các giá trị trong đầu ra của tệp (như trên).

Tôi có thể sử dụng HashTable và thêm thông tin vào nó, sau đó chỉ cần sao chép dữ liệu của nó vào Danh sách. Có giải pháp nào khác không?

Trả lời

73

Tại sao bạn cần lưu trữ nó trong một số List? Bạn có thực sự yêu cầu dữ liệu được sắp xếp hoặc hỗ trợ tìm kiếm dựa trên chỉ mục không?

Tôi khuyên bạn nên lưu trữ dữ liệu trong một Set. Nếu đặt hàng không quan trọng, bạn nên sử dụng HashSet. Tuy nhiên, nếu bạn muốn giữ gìn trật tự, bạn có thể sử dụng LinkedHashSet.

+1

Tại sao? Danh sách Nguyên nhân được sử dụng thường xuyên nhất và rất dễ làm việc. Tôi nghĩ rằng nếu bạn viết mã cho các nhà phát triển khác thì tốt hơn là trả về một loại Danh sách hơn bất kỳ loại nào khác. – EugeneP

+0

Không nhất thiết. Trường hợp duy nhất mà bạn cần danh sách là nếu bạn muốn truy cập ngẫu nhiên vào các mục trong bộ sưu tập. Nếu không nó sẽ là thích hợp hơn để đi với đồng bằng HashSet hoặc LinkedHashSet. –

+0

Theo tôi, mã sẽ sạch hơn khi bạn sử dụng indice. Bạn có quyền kiểm soát "bạn đang ở đâu" bên trong cấu trúc dữ liệu. Nó có thể đến từ kinh nghiệm của tôi với ngôn ngữ C. – EugeneP

16

Bạn có thể kiểm tra list.contains() trước khi thêm.

if(!list.contains(value)) { 
    list.add(value); 
} 

Tôi đoán nó sẽ là hiển nhiên! Tuy nhiên, việc thêm các mục vào một HashSet và sau đó tạo một danh sách từ tập hợp này sẽ hiệu quả hơn.

+0

Tôi cho rằng nó sử dụng phương thức "bằng"? – EugeneP

+0

Có nó sử dụng bằng() trên chuỗi trong nội bộ. –

+0

Đúng. Cảm ơn. Trong trường hợp của tôi sẽ thích hợp hơn, vì mã sẽ được giữ sạch sẽ. Nhưng tôi đoán thuật toán HashTable nhanh hơn phương thức chứa, trừ khi chúng sử dụng một HashTable trong nội bộ. – EugeneP

61

Nếu bạn có một bản sao List chứa, và bạn muốn có một List mà không có, bạn có thể làm:

List<String> newList = new ArrayList<String>(new HashSet<String>(oldList)); 

Đó là, quấn danh sách cũ thành một tập để loại bỏ bản sao và quấn bộ đó trong danh sách một lần nữa.

+0

Tôi đoán, không có gì đảm bảo rằng việc sắp xếp 'newList' sẽ giống như một' oldList', hay? – Marvin

+7

O.k. Tôi tìm thấy câu trả lời cho bình luận của tôi: Nếu bạn sử dụng 'LinkedHashSet' thay vì' HashSet', bạn giữ nguyên thứ tự. – Marvin

1

Dưới đây là cách tôi giải quyết nó:

import groovy.io.*; 
def arr = ["5", "5", "7", "6", "7", "8", "0"] 
List<String> uniqueList = new ArrayList<String>(new HashSet<String>(arr.asList())); 
System.out.println(uniqueList) 
0
class HashSetList<T extends Object> 
    extends ArrayList<T> { 

    private HashSet<Integer> _this = new HashSet<>(); 

    @Override 
    public boolean add(T obj) { 
     if (_this.add(obj.hashCode())) { 
      super.add(obj); 
      return true; 
     } 
     return false; 
    } 
} 

bây giờ tôi sử dụng những loại cấu trúc cho các chương trình nhỏ, tôi có nghĩa là bạn có ít overhead để có getter và setter nhưng độc đáo. Hơn nữa, bạn có thể ghi đè lên hashCode để quyết định mục của bạn bằng với mục khác.

+0

Ý tưởng hay, nhưng ... những gì về loại bỏ và thêm (int, *) vv? Giải pháp này chưa hoàn thành. –

Các vấn đề liên quan