En utilisant à la fois Java 8 et Java 11, tenez compte des éléments suivants TreeSet
avec un String::compareToIgnoreCase
comparateur:
final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");
System.out.println(languages); // [c++, java, python]
Lorsque j'essaie de supprimer les éléments exacts présents dans le TreeSet
, cela fonctionne: tous ceux spécifiés sont supprimés:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
Cependant, si j'essaie de supprimer à la place plus que ce qui est présent dans le TreeSet
, l'appel ne supprime rien du tout (ce n'est pas un appel ultérieur mais appelé à la place de l'extrait ci-dessus):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
Qu'est-ce que je fais mal? Pourquoi se comporte-t-il de cette façon?
Modifier: String::compareToIgnoreCase
est un comparateur valide:
(l, r) -> l.compareToIgnoreCase(r)
Réponses:
Voici le javadoc de removeAll () :
Dans votre deuxième expérience, vous êtes dans le premier cas du javadoc. Il itère donc sur "java", "c ++", etc. et vérifie s'ils sont contenus dans l'ensemble renvoyé par
Set.of("PYTHON", "C++")
. Ils ne le sont pas, ils ne sont donc pas supprimés. Utilisez un autre TreeSet utilisant le même comparateur que l'argument, et cela devrait fonctionner correctement. L'utilisation de deux implémentations Set différentes, l'une utilisantequals()
l'autre et l'autre utilisant un comparateur, est une chose dangereuse à faire.Notez qu'un bogue est ouvert à ce sujet: [JDK-8180409] TreeSet removeAll comportement incohérent avec String.CASE_INSENSITIVE_ORDER .
la source
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.