web-dev-qa-db-ja.com

配列リストでremove(object o)を呼び出すと、オブジェクトをどのように比較しますか?

Javaの配列リストでremove(object o)を呼び出すと、オブジェクトをどのように比較して、削除する正しいオブジェクトを見つけるのですか?ポインタを使用しますか?または、インターフェイスComparableを使用してオブジェクトを比較しますか?

30
Thomas Winsnes

ArrayListremove()は、Equalメソッドのオブジェクト実装に依存しています。実装が行われていない場合、オブジェクトはObjectEqualsの実装によって削除されます。これは、実際にはポインターの比較です。

ArrayListのドキュメントから-

より正式には、(o==null ? get(i)==null : o.equals(get(i)))(そのような要素が存在する場合)のように、インデックスiが最も低い要素を削除します。

オブジェクトequalメソッドのドキュメント-

クラスObjectのequalsメソッドは、オブジェクトに対して最も識別可能な同等の関係を実装します。つまり、null以外の参照値xyの場合、このメソッドは、xyが同じオブジェクトを参照している場合にのみtrueを返します。 (x == yの値はtrueです)。

17
Eric

この種の情報については、常にAPIを参照する必要があります。

ArrayList.remove(Object o) :指定された要素が存在する場合、このリストから最初に出現する要素を削除します。リストに要素が含まれていない場合、変更されません。より正式には、(o==null ? get(i)==null : o.equals(get(i)))(そのような要素が存在する場合)のように、インデックスiが最も低い要素を削除します。

おそらくあなたはこれを例えばと混同していました。 TreeSet

Java.util.TreeSet :セットによって維持される順序(明示的なコンパレータが提供されているかどうかに関係なく)は、equalsと一致である必要があることに注意してください。 Setインターフェース。 (equalsとの整合性の正確な定義については、ComparableまたはComparatorを参照してください。)これは、Setインターフェイスがequals操作で定義されているが、TreeSetインスタンスであるためです。 compareTo(またはcompare)メソッドを使用してすべての要素の比較を実行するため、このメソッドによって等しいと見なされる2つの要素は、セットの観点からは等しいです。

(残念ながら、例: TreeSet.remove メソッド自体には、上記の警告を明示的に思い出させるものはありませんが、少なくともクラスのドキュメントの一番上に目立つように配置されています)


実例

次のスニペットは、equalsを使用するコレクション(ArrayListなど)とcompare/compareToを使用するコレクション(TreeSetなど)の動作の違いを示しています。

import Java.util.*;

public class CollectionEqualsCompareTo {
    static void test(Collection<Object> col, Object o) {
        col.clear();
        col.add(o);
        System.out.printf("%b %b %b %b%n",
            col.contains(o),
            col.remove(o),
            col.contains(o),
            col.isEmpty()
        );
    }
    public static void main(String[] args) {
        Object broken1 = new Comparable<Object>() {
            // Contract violations!!! Only used for illustration!
            @Override public boolean equals(Object o)    { return true; }
            @Override public int compareTo(Object other) { return -1;   }
        };
        Object broken2 = new Comparable<Object>() {
            // Contract violations!!! Only used for illustration!
            @Override public boolean equals(Object o)    { return false; }
            @Override public int compareTo(Object other) { return 0;     }
        };
        test(new ArrayList<Object>(), broken1); // true true false true
        test(new TreeSet<Object>(),   broken1); // false false false false
        test(new ArrayList<Object>(), broken2); // false false false false
        test(new TreeSet<Object>(),   broken2); // true true false true
    }
}
8

docs あなたの質問に答えてください:

指定された要素の単一のインスタンスが存在する場合は、このコレクションから削除します(オプションの操作)。より正式には、要素eを削除して(o==null ? e==null : o.equals(e))、コレクションにそのような要素が1つ以上含まれている場合。

1
leonbloy

equals()を使用します

docs から:

指定された要素が存在する場合は、このリストから最初に出現する要素を削除します。リストに要素が含まれていない場合、変更されません。より正式には、(o == null?get(i)== null:o.equals(get(i)))(そのような要素が存在する場合)のように、インデックスiが最も低い要素を削除します。このリストに指定された要素が含まれている場合(または、呼び出しの結果としてこのリストが変更された場合)はtrueを返します。

1
YGL