Beachten Sie bei Verwendung von Java 8 und Java 11 Folgendes TreeSet
mit einem String::compareToIgnoreCase
Komparator:
final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");
System.out.println(languages); // [c++, java, python]
Wenn ich versuche, die genauen Elemente in zu entfernen TreeSet
, funktioniert dies: Alle angegebenen Elemente werden entfernt:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
Wenn ich jedoch versuche, stattdessen mehr zu entfernen , als in der vorhanden ist TreeSet
, entfernt der Aufruf überhaupt nichts (dies ist kein nachfolgender Aufruf, sondern wird anstelle des obigen Snippets aufgerufen):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
Was mache ich falsch? Warum verhält es sich so?
Bearbeiten: String::compareToIgnoreCase
ist ein gültiger Komparator:
(l, r) -> l.compareToIgnoreCase(r)
Antworten:
Hier ist das Javadoc von removeAll () :
In Ihrem zweiten Experiment befinden Sie sich im ersten Fall des Javadoc. Es iteriert also über "Java", "C ++" usw. und prüft, ob sie in dem von zurückgegebenen Set enthalten sind
Set.of("PYTHON", "C++")
. Sie sind nicht, also werden sie nicht entfernt. Verwenden Sie ein anderes TreeSet mit demselben Komparator wie das Argument, und es sollte einwandfrei funktionieren. Die Verwendung von zwei verschiedenen Set-Implementierungen, von denen eineequals()
und die andere einen Komparator verwendet, ist in der Tat eine gefährliche Sache.Beachten Sie, dass hier ein Fehler aufgetreten ist : [JDK-8180409] TreeSet removeAll inkonsistentes Verhalten mit String.CASE_INSENSITIVE_ORDER .
quelle
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.