Используя 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]
Что я делаю неправильно? Почему так себя ведет?
Изменить: String::compareToIgnoreCase
является действительным компаратором:
(l, r) -> l.compareToIgnoreCase(r)
Ответы:
Вот javadoc для removeAll () :
Во втором эксперименте вы находитесь в первом случае с Javadoc. Таким образом, он перебирает «java», «c ++» и т. Д. И проверяет, содержатся ли они в множестве, возвращаемом функцией
Set.of("PYTHON", "C++")
. Их нет, поэтому они не удалены. Используйте другой TreeSet, используя тот же компаратор, что и аргумент, и он должен работать нормально. Использование двух разных реализаций Set, одна из которых используетсяequals()
, а другая использует компаратор, действительно опасно.Обратите внимание, что по этому поводу открыта ошибка: [JDK-8180409] TreeSet removeAll несовместимое поведение с String.CASE_INSENSITIVE_ORDER .
источник
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.