2012-04-16 49 views
12

在我發佈這個問題之前,我發現有點類似的問題發佈here。但答案是基於String。不過,我在這裏有不同的情況。我不是想要刪除String,而是另一個名爲AwardYearSource的對象。這個類有一個int屬性叫做year。所以我想根據年份刪除重複項目。即如果2010年有不止一次提及,我想刪除該AwardYearSource對象。我怎樣才能做到這一點?如何從基於自定義Java對象而不是基元類型的列表中刪除重複項?

+0

Java的8路也相當不錯:http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC 2016-12-09 07:53:32

回答

45

刪除基於字段內容如下(維持秩序)的最簡單方法:

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

謝謝。它解決了我的問題。不過,我將代碼的第一行更改爲Map map = new LinkedHashMap (); ....否則它不會編譯。 – WowBow 2012-04-16 15:44:58

+5

對不起,'<>'語法只適用於Java 7. – 2012-04-16 15:47:45

+0

好戲。感謝解決我的問題。 – James 2017-03-29 19:03:22

0

你可以使用地圖和存儲您的對象與去年作爲重點:

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

etc. 

在結束時,地圖將在今年包含唯一的值,您可以用數值方法調用:

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

用int作爲鍵類型,將你的類作爲值類型創建一個HashMap對象。然後遍歷該列表,並使用每一個元素插入到地圖中:

mymap.put(source.year, source); 

然後從原著列表中刪除所有的元素和迭代在地圖上,並插入每個元素到列表中。

+0

真的嗎?你能否提供更多細節?儘管至少有一個迭代器是不必要的 - 請參閱其他一些答案。如果在線程環境中使用,這會產生一些令人討厭的副作用。 – 2012-04-16 15:59:52

+0

也許您已在滿錯誤的答案上發佈此評論?我在我的解決方案中沒有看到任何迭代器,並且它非常安全。 – smichak 2012-04-16 16:10:55

+0

您明確提到迭代,並且您將至少使用一個_implicit_(在for-each構造的情況下生成的編譯器)迭代器。如果這是打包在自己的方法(它應該是),然後從原始列表中刪除項目是絕對不**線程安全。 – 2012-04-16 16:40:51

1

另一種方法是覆蓋hashCode()equals(Object obj)爲您的對象。既然它只有一個你想用來確定平等的領域,這是非常簡單的。喜歡的東西:

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

然後,你可以堅持所有的對象爲Set刪除重複:

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

如果您AwardYearSource類重寫equals和hashCode方法(Eclipse可以同時生成),然後你可以將它們添加到Set。該集不會包含任何重複。

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

輸出是[2000]。集合中只有一個項目。

1

相當簡單。儘管有些東西讓我誤解了地圖版本(不是我懷疑他們會工作,但它似乎有點矯枉過正,儘管這個版本在這方面不一定更好)。
答案是功能性和線程安全的(假設AwardYearSource是不可變的)。

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

決賽圈太多了 – 2012-04-16 18:21:33

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

這應該有助於其中,複製是基於特定的屬性(或屬性的組合)決定,今年在這種情況下。希望這可以幫助。

相關問題