2012-04-16 14 views
12

Trước khi tôi đăng câu hỏi này, tôi đã tìm thấy câu hỏi tương tự bằng cách nào đó được đăng here. Nhưng câu trả lời dựa trên một String. Tuy nhiên, tôi có một tình huống khác ở đây. Tôi không cố gắng để loại bỏ String nhưng đối tượng khác được gọi là AwardYearSource. Lớp này có thuộc tính int được gọi là năm. Vì vậy, tôi muốn loại bỏ các bản sao dựa trên năm. tức là nếu có năm 2010 được đề cập nhiều lần, tôi muốn xóa đối tượng AwardYearSource đó. Làm thế nào tôi có thể làm điều đó?Làm thế nào để loại bỏ các bản sao từ một danh sách dựa trên một đối tượng java tùy chỉnh không phải là một kiểu nguyên thủy?

+0

Cách Java 8 cũng khá đẹp: http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC

Trả lời

45

Cách đơn giản nhất để loại bỏ các yếu tố dựa trên một lĩnh vực như sau (giữ gìn trật tự):

Map<Integer, AwardYearSource> map = new LinkedHashMap<>(); 
for (AwardYearSource ays : list) { 
    map.put(ays.getYear(), ays); 
} 
list.clear(); 
list.addAll(map.values()); 
+1

Cảm ơn bạn. Nó giải quyết vấn đề của tôi. Tuy nhiên tôi đã thay đổi dòng đầu tiên của mã của bạn thành Map map = new LinkedHashMap (); .... nếu không nó sẽ không biên dịch. – WowBow

+5

Xin lỗi, cú pháp '<>' chỉ hoạt động trong Java 7. –

+0

Mẹo hay. Cảm ơn giải quyết vấn đề của tôi. – James

0

Bạn có thể sử dụng bản đồ và lưu trữ đối tượng của bạn với năm như một chìa khóa:

Map<Integer, AwardYearSource> map = new HashMap<Integer, AwardYearSource>(); 
map.put(someAwardYearSource1.getYear(), someAwardYearSource1); 
map.put(someAwardYearSource2.getYear(), someAwardYearSource2); 

etc. 

cuối cùng bản đồ sẽ chứa các giá trị độc đáo của năm, mà bạn có thể gọi với phương pháp giá trị:

Collection<AwardYearSource> noDups = map.values(); 
0

. Tạo một đối tượng HashMap với int là kiểu khóa và lớp của bạn làm kiểu giá trị. Sau đó lặp trên danh sách và chèn từng yếu tố để bản đồ sử dụng:

mymap.put(source.year, source); 

Sau đó, loại bỏ tất cả các yếu tố từ danh sách origianl và duyệt qua bản đồ và chèn mỗi phần tử vào danh sách.

+0

Thật sao? Bạn có thể cung cấp thêm chi tiết? Mặc dù ít nhất một trong các trình vòng lặp là không cần thiết - hãy xem một số câu trả lời khác. Và điều này sẽ có một số tác dụng phụ khó chịu, nếu được sử dụng trong bối cảnh luồng. –

+0

Có thể bạn đã đăng nhận xét này về câu trả lời sai? Tôi không thấy bất kỳ trình lặp nào trong các giải pháp của tôi và nó khá an toàn. – smichak

+0

Bạn đề cập một cách rõ ràng về iterate, và bạn sẽ sử dụng ít nhất một trình biên dịch _implicit_ (trình tạo được tạo ra, trong trường hợp của từng cấu trúc). Nếu điều này đang được đóng gói trong phương pháp riêng của nó (mà nó nên được), sau đó loại bỏ các mục từ danh sách ban đầu là ** hoàn toàn KHÔNG ** threadsafe. –

1

Một cách khác là ghi đè hashCode()equals(Object obj) cho đối tượng của bạn. Vì nó chỉ có một trường mà bạn muốn sử dụng để xác định sự bình đẳng, điều này khá đơn giản. Một cái gì đó như:

public boolean equals(Object obj) { 
    if (obj == null || !(obj instanceof AwardYearSource)) { 
    return false; 
    } 
    return (this.year == ((AwardYearSource)obj).year); 
} 
public int hashCode() { 
    return this.year; 
} 

Sau đó, bạn chỉ có thể dính vào tất cả các đối tượng vào một Set để loại bỏ các bản sao:

Set<AwardYearSource> set = new Set<AwardYearSource>(); 

set.add(new AwardYearSource(2011)); 
set.add(new AwardYearSource(2012)); 
set.add(new AwardYearSource(2011)); 

for (AwardYearSource aws : set) { 
    System.out.println(aws.year); 
} 
0

Nếu ghi đè lớp AwardYearSource của bạn bằng và phương pháp hashcode (Eclipse có thể tạo ra cả hai), sau đó bạn có thể thêm chúng vào một Set. Tập hợp sẽ không chứa bất kỳ bản sao nào.

public class AwardYearSource 
{ 
    private final int year; 

    public AwardYearSource(int year) 
    { 
     this.year = year; 
    } 

    @Override 
    public int hashCode() 
    { 
     final int prime = 31; 
     int result = 1; 
     result = prime * result + year; 
     return result; 
    } 

    @Override 
    public boolean equals(Object obj) 
    { 
     if (this == obj) 
      return true; 
     if (obj == null) 
      return false; 
     if (getClass() != obj.getClass()) 
      return false; 
     AwardYearSource other = (AwardYearSource) obj; 
     if (year != other.year) 
      return false; 
     return true; 
    } 

    @Override 
    public String toString() 
    { 
     return String.valueOf(year); 
    } 


    public static void main(String[] args) 
    { 
     Set<AwardYearSource> set = new HashSet<AwardYearSource>(); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 
     set.add(new AwardYearSource(2000)); 

     System.out.println(set); 
    } 
} 

Kết quả là [2000]. Chỉ có một mục trong tập hợp.

1

Khá đơn giản. Mặc dù có điều gì đó khiến tôi lo ngại về các phiên bản bản đồ (không phải là tôi nghi ngờ họ sẽ làm việc, nó có vẻ như quá mức, bằng cách nào đó - mặc dù phiên bản này không nhất thiết phải tốt hơn về vấn đề đó).
Câu trả lời là chức năng và luồng an toàn (giả sử AwardYearSource là không thay đổi).

public static List<AwardYearSource> removeDuplicateYears(
              final Collection<AwardYearSource> awards) { 
    final ArrayList<AwardYearSource> input = new ArrayList<AwardYearSource>(awards); 
    // If there's only one element (or none), guaranteed unique. 
    if (input.size() <= 1) { 
     return input; 
    } 
    final HashSet<Integer> years = new HashSet<Integer>(input.size(), 1); 
    final Iterator<AwardYearSource> iter = input.iterator(); 
    while(iter.hasNext()) { 
     final AwardYearSource award = iter.next(); 
     final Integer year = award.getYear(); 
     if (years.contains(year)) { 
      iter.remove(); 
     } else { 
      years.add(year); 
     } 
    } 
    return input;  

} 
+0

Quá nhiều trận chung kết –

0
Set<Integer> set = new HashSet<>(); 
list.removeIf(i -> set.contains(i.getYear()) ? true : !set.add(i.getYear())); 

Điều này sẽ giúp trong đó, trùng lặp được quyết định dựa trên tài sản nhất định (hoặc kết hợp các thuộc tính), năm trong trường hợp này. Hi vọng điêu nay co ich.