Почему не вынимая из TreeSet с помощью пользовательского компаратора удалить больший набор элементов?

Nikolas:

Использование как Java 8 и Java 11, рассмотрим следующий TreeSetс String::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]

Что я делаю неправильно? Почему он ведет себя таким образом?

Edit: String::compareToIgnoreCaseявляется действительным компаратор:

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

Вот Javadoc из RemoveAll () :

Эта реализация определяет, является меньшим из этого множества и указанной коллекции, с помощью вызова метода размера на каждом. Если этот набор содержит меньше элементов, то перебирает реализацию над этим набором, проверяя каждый элемент, возвращенный итератором, в свою очередь, чтобы увидеть, если он содержится в указанной коллекции. Если это так, содержащиеся, он удаляется из этого набора с методом удалить итератор. Если указанная коллекция имеет меньше элементов, то итерация осуществления в течение указанной коллекции, удаляя из этого набора каждого элемента, возвращенный итератором, используя метод удалить это множество.

В вашем втором эксперименте, вы в первом случае Javadoc. Так перебирает «Java», «C ++» и т.д. , и проверяет , если они содержатся в множестве возвращаемого Set.of("PYTHON", "C++"). Они не так , поэтому они не удаляются. Используйте другой TreeSet , используя тот же компаратор в качестве аргумента, и он должен работать нормально. Использование двух различных реализаций Set, одна с использованием equals(), а также другую , используя компаратор, это опасная вещь , чтобы сделать действительно.

Обратите внимание , что есть ошибка открыто об этом: [JDK-8180409] TreeSet RemoveAll непоследовательность с String.CASE_INSENSITIVE_ORDER .

рекомендация

отhttp://10.200.1.11:23101/article/api/json?id=427293&siteId=1