なぜ、アイテムの大規模なセットを削除するカスタムコンパレータとTreeSetのから削除されませんか?

ニコラス:

Javaの8とJava 11の両方を使用して、以下のことを考えるTreeSetString::compareToIgnoreCase、コンパレータ:

final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");

System.out.println(languages);                 // [c++, java, python]

私は中に存在正確な要素を削除しようとするとTreeSet、それが動作します:指定されたもののすべてが削除されます。

languages.removeAll(Arrays.asList("PYTHON", "C++"));

System.out.println(languages);                 // [java]

私が代わりに削除しようとする場合は、より多くの中に存在するよりもTreeSet、呼び出しは(これは後続の呼び出しではなく、代わりに上記のスニペットのと呼ばれる)のすべてでは何も削除されません。

languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));

System.out.println(languages);                 // [c++, java, python]

何が私が間違っているのでしょうか?なぜそれがこのように動作するのでしょうか?

編集:String::compareToIgnoreCase有効なコンパレータです。

(l, r) -> l.compareToIgnoreCase(r)
JB Nizet:

ここでのjavadocのだがremoveAll()は

この実装は、それぞれにサイズメソッドを呼び出して、このセットおよび指定されたコレクションのうちの小さい方であるかを決定します。このセットは、それが指定されたコレクションに含まれているかどうかを確認するために順番に反復子によって返された各要素をチェック少ない要素、このセットの上に、その後の実装繰り返し処理を、持っている場合。それはそう含まれている場合は、反復子のremoveメソッドを使用してこのセットから削除されます。指定されたコレクションが少ない要素を持っている場合は、このセットから各要素を削除指定されたコレクションで実装を繰り返し処理は、このセットのremoveメソッドを使用して、反復子によって返されました。

あなたの第二の実験では、javadocツールの最初のケースにしています。によって返された彼らはセットに含まれている場合などの「Java」、「C ++」を、反復処理をチェック、それはそうSet.of("PYTHON", "C++")彼らは削除していないので、彼らは、ありません。引数と同じコンパレータを使用して別のTreeSetのを使用し、それが正常に動作するはずです。二つの異なるセットの実装形態では、1つ使用して使用するequals()と、コンパレータを使用して他のものを、実際に行うには危険なものです。

:これについて開かれたバグがあることに注意してくださいString.CASE_INSENSITIVE_ORDERで[JDK-8180409] TreeSetのがremoveAll一貫性のない動作が

おすすめ

転載: http://10.200.1.11:23101/article/api/json?id=427297&siteId=1