2012-04-16 4 views
12

私はこの質問を投稿する前に、何とか似たような質問が見つかったと投稿しましたhere。しかし、答えは文字列に基づいていました。しかし、私はここで別の状況があります。私はStringを削除しようとしていませんが、AwardYearSourceという別のオブジェクトを削除しようとしています。このクラスは、年というint属性を持っています。だから私は年に基づいて重複を削除したい。つまり、2010年が2回以上言及されている場合は、そのAwardYearSourceオブジェクトを削除したいと考えています。どうやってやるの?プリミティブ型ではなくカスタムJavaオブジェクトに基づいてリストから重複を削除するにはどうすればよいですか?

+0

Java 8ウェイもかなりいいです:http://stackoverflow.com/questions/23699371/java-8-distinct-by-property – JDC

答えて

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

+5

申し訳ありませんが、 '<>'構文はJava 7でのみ動作します。 –

+0

素敵なトリックです。ありがとう、私の問題を解決する。 – James

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オブジェクトを作成します。次に、リストを反復し、使用して地図に各要素を挿入:次いでorigianlリストからすべての要素を削除してマップを反復処理し、リストに各要素を挿入

mymap.put(source.year, source); 

を。

+0

本当ですか?多分詳細を教えてください。イテレータの少なくとも1つは不要ですが、他の回答のいくつかを参照してください。スレッド化されたコンテキストで使用されると、これはいくつかの厄介な副作用を伴います。 –

+0

あなたは間違った答えにこのコメントを投稿したことがありますか?私のソリューションにはイテレータは見当たりません。スレッドセーフです。 – smichak

+0

明示的にiterateを記述すると、少なくとも1つの_implicit_(for-each構文の場合、コンパイラが生成する)イテレータを使用します。これが独自の方法でパッケージ化されている場合は、元のリストから項目を削除することは絶対に**スレッドセーフではありません。 –

1

もう1つの方法は、オブジェクトにhashCode()equals(Object obj)を上書きすることです。平等を判断するために使いたいフィールドが1つしかないので、これはかなり簡単です。ような何か:

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にすべてのオブジェクトを固執することができます:あなたのAwardYearSourceクラスのオーバーライドする場合

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

に等しいとhashCodeメソッド(Eclipseは両方を生成することができます)、その後、それらをセットに追加することができます。セットには重複が含まれません。

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つだけです。

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

ファイナルが多すぎます –

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

これは、複製が特定のプロパティ(またはプロパティの組み合わせ)に基づいて決定され、この場合、年を助けるべきです。お役に立てれば。

関連する問題