0

個人を扱うときのremoveAllメソッドのこの奇妙な動作を発見しました。AbstractSetsComparators

比較されるコレクションのサイズに応じて、異なるコンパレータが使用されます。

実際には API で文書化されていますが、その背後にある理由はまだわかりません。

コードは次のとおりです。

import java.util.Comparator;
import java.util.Set;
import java.util.Stack;
import java.util.TreeSet;

public class Test {
    public static void main(String[] args) {
        // Any comparator. For this example, the length of a string is compared
        Set<String> set = new TreeSet<String>(new Comparator<String>() {
                @Override
                public int compare(String o1, String o2) {
                        return o1.length() - o2.length();
                }
        });

        set.add("a");
        set.add("aa");
        set.add("aaa");
        set.add("aaaa");
        System.out.println(set); // output: [a, aa, aaa, aaaa]

        Stack<String> stack = new Stack<String>();
        stack.push("b");
        stack.push("bb");
        stack.push("bbb");
        stack.push("bbbb");

        set.removeAll(stack); // NO ITEMS ARE REMOVED from the set
        System.out.println(set); // output: [a, aa, aaa, aaaa]

        // Now let's see what happens if I remove an object from the stack
        stack.pop();
        set.removeAll(stack); // ALL ITEMS from the stack are removed from the
                                                        // set
        System.out.println(set); // output: [aaaa]

        /* Reason for this strange behaviour: Depending on the size of the
         * passed Collection, TreeSet uses either the remove() function of
         * itself, or from the Collection object that was passed. While the
         * remove() method of the TreeSet uses the comparator to determine
         * equality, the remove() method of the passed usually determines
         * equality by calling equals() on its objects.
         */
    }
}

ここに JavaDoc があります。

4

2 に答える 2

0

セットには異なる同等基準があるため、基本的に未定義の動作を作成しました。何らかの方法でコレクションを組み合わせることは、それらが同じである場合にのみ機能します。A.equals(B)あなたは基本的に と同じ結果をもたらさなければならない契約に違反していB.equals(A)ます。

Comparable : 自然順序付けが equals と一致することを強くお勧めします (必須ではありません)。これは、明示的な比較子のないソートされたセット (およびソートされたマップ) が、自然な順序付けが equals と矛盾する要素 (またはキー) で使用されると、「奇妙な」動作をするためです。特に、そのようなソート済みセット (またはソート済みマップ) は、equals メソッドに関して定義されているセット (またはマップ) の一般規約に違反しています。

于 2013-08-08T10:23:45.870 に答える