Usando Java 8 y Java 11, considere lo siguiente TreeSet
con un 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]
Cuando intento eliminar los elementos exactos presentes en el TreeSet
, funciona: se eliminan todos los especificados:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
Sin embargo, si intento eliminar en su lugar más de lo que está presente en la TreeSet
llamada, la llamada no elimina nada (esta no es una llamada posterior, sino que se llama en lugar del fragmento anterior):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
¿Qué estoy haciendo mal? ¿Por qué se comporta de esta manera?
Editar: String::compareToIgnoreCase
es un comparador válido:
(l, r) -> l.compareToIgnoreCase(r)
Respuestas:
Aquí está el javadoc de removeAll () :
En tu segundo experimento, estás en el primer caso del javadoc. Por lo tanto, itera sobre "java", "c ++", etc. y comprueba si están contenidos en el conjunto devuelto por
Set.of("PYTHON", "C++")
. No lo son, así que no se eliminan. Use otro TreeSet usando el mismo comparador como argumento, y debería funcionar bien. Usar dos implementaciones de Set diferentes, una usandoequals()
y la otra usando un comparador, es algo realmente peligroso.Tenga en cuenta que hay un error abierto sobre esto: [JDK-8180409] TreeSet removeTodo comportamiento inconsistente con String.CASE_INSENSITIVE_ORDER .
fuente
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.