2つのArrayListが互いに異なるかどうかを確認するにはどうすればよいですか?違いは何でも構いませんが、それらが同じではないかどうかを知りたいだけです。
私は毎分データベースからスコアリストを取得していますが、取得したスコアリストが1分前に取得したものと異なる場合にのみ、クライアントに送信します。
現在、ArrayListの値は、実際に作成したクラスです(名前、レベル、ランク、スコアを含む)。
equals()
を実装する必要がありますか?
2つの配列リストに順序に関係なく同じ値が含まれているかどうかを確認する簡単な方法を次に示します。
//the name of the method explains it well...
public boolean isTwoArrayListsWithSameValues(ArrayList<Object> list1, ArrayList<Object> list2)
{
//null checking
if(list1==null && list2==null)
return true;
if((list1 == null && list2 != null) || (list1 != null && list2 == null))
return false;
if(list1.size()!=list2.size())
return false;
for(Object itemList1: list1)
{
if(!list2.contains(itemList1))
return false;
}
return true;
}
Joachimが指摘したように、ほとんどのアプリケーションでは、 List.equals(Object o)
定義が機能します:
指定されたオブジェクトとこのリストが等しいかどうかを比較します。指定されたオブジェクトもリストであり、両方のリストが同じサイズであり、2つのリスト内の対応する要素のペアがすべて等しい場合にのみ、
true
を返します。 (2つの要素e1
とe2
は、(e1==null ? e2==null : e1.equals(e2))
の場合に等しい。)つまり、2つのリストは、同じ順序で同じ要素が含まれている場合に等しいと定義されます。この定義により、equals
メソッドのさまざまな実装でList
インターフェイスが適切に機能することが保証されます。
ただし、使用方法によっては、期待どおりに機能しない場合があります。たとえば、List<int[]>
がある場合、配列はequals
からObject
を継承します。これは、参照IDとして同等性を定義します。
List<int[]> list1 = Arrays.asList(new int[] { 1, 2, 3 });
List<int[]> list2 = Arrays.asList(new int[] { 1, 2, 3 });
System.out.println(list1.equals(list2)); // prints "false"
また、異なる型パラメーターを持つ2つのリストをequals
にすることができます。
List<Number> list1 = new ArrayList<Number>();
List<String> list2 = new ArrayList<String>();
System.out.println(list1.equals(list2)); // prints "true"
また、リストには同じタイプの要素が含まれている必要があることにも触れました。要素が同じタイプではなく、equals
である別の例を次に示します。
List<Object> list1 = new ArrayList<Object>();
List<Object> list2 = new ArrayList<Object>();
list1.add(new ArrayList<Integer>());
list2.add(new LinkedList<String>());
System.out.println(list1.equals(list2)); // prints "true"
したがって、平等があなたに何を意味するかを明確に定義しない限り、質問には非常に異なる答えが含まれることがあります。ただし、最も実用的な目的には、List.equals
で十分です。
equals
の実装について更新後の情報は、List.equals
が問題なく動作することを示唆しています。提供要素がequals
を適切に実装する(上記のAPIドキュメントに従って、List<E>.equals
がnon _null
-要素でE.equals
を呼び出すため) )。
したがって、この場合、たとえばList<Player>
がある場合、o instanceof Player
があり、関連するフィールドでPlayer
を返すには、true
が@Override equals(Object o)
でなければなりません。それらはすべてequals
(参照型の場合)または==
(プリミティブの場合)です。
もちろん、@Override equals
を使用するときは、@Override int hashCode()
も使用する必要があります。かろうじて受け入れられる最小値はreturn 42;
です。少し良いのはreturn name.hashCode();
;です。最善の方法は、equals
を定義するすべてのフィールドを含む式を使用することです。適切なIDEはequals/hashCode
メソッドを自動的に生成できます。
Object.equals(Object)
Object.hashCode()
Java.lang.Comparable
-ここでは必要ありませんが、別の重要なJava APIコントラクトequals/hashCode
コンボの場合:
equals
対==
の場合:
equals()
を使用します。リスト内の要素がequals()
を正しく実装している限り、正しい値を返します。
値の順序を無視する場合を除き、2つのSet
オブジェクトに値をダンプし、equals()
を使用して値を比較する必要があります。
@Joachim Sauerが彼の答えで言及したように、リストが等しく、それらのコンテンツが等しく実装されていれば、equalsは機能するはずです。ただし、アイテムが同じ「順序」にない場合は、チェックに包含を使用しないため、機能しません。この意味で、@ jarnbjoで言及されている「厳密な」同等性をチェックします。
//From Android's Arraylist implementation
Iterator<?> it = that.iterator();
for (int i = 0; i < s; i++) {
Object eThis = a[i];
Object eThat = it.next();
if (eThis == null ? eThat != null : !eThis.equals(eThat)) {
return false;
}
}
しかし、私は多少異なる振る舞いを望んでいました。注文などは気にしませんでした。私が望んだのは、2つに同じアイテムが含まれていないことを確認することだけでした。私の解決策、
//first check that both are not null and are of same length. (not shown here)
//if both match, pull out the big guns as below
...
List<Object> comparedList = new ArrayList<>(listOne);
comparedList.removeAll(listTwo);
if(comparedList.size() != 0) //there are differences between the two
最初はremoveAll
で、次にcontains
によって呼び出されるremoveAll
で2回ループするため、パフォーマンスが低下します。
私のリストは短いことが保証されていたので、ヒットを気にしませんでした。
それらを文字列に変換してから、次のように比較できます
list1.toString().equals(list2.toString())