Usando Java 8 e Java 11, considere o seguinte TreeSet
com um String::compareToIgnoreCase
comparador:
final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");
System.out.println(languages); // [c++, java, python]
Quando tento remover os elementos exatos presentes no TreeSet
, ele funciona: todos os especificados são removidos:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
No entanto, se eu tentar remover mais do que o presente TreeSet
, a chamada não removerá nada (essa não é uma chamada subsequente, mas chamada em vez do snippet acima):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
O que estou fazendo errado? Por que se comporta dessa maneira?
Editar: String::compareToIgnoreCase
é um comparador válido:
(l, r) -> l.compareToIgnoreCase(r)
Respostas:
Aqui está o javadoc de removeAll () :
Em seu segundo experimento, você está no primeiro caso do javadoc. Por isso, itera sobre "java", "c ++" etc., e verifica se estão contidos no conjunto retornado por
Set.of("PYTHON", "C++")
. Eles não são, portanto não são removidos. Use outro TreeSet usando o mesmo comparador que o argumento e deve funcionar bem. Usar duas implementações diferentes de Set, uma usandoequals()
e a outra usando um comparador, é algo perigoso de se fazer.Observe que há um erro aberto sobre isso: [JDK-8180409] TreeSet removeAll comportamento inconsistente com String.CASE_INSENSITIVE_ORDER .
fonte
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.