Menggunakan Java 8 dan Java 11, pertimbangkan yang berikut TreeSet
dengan String::compareToIgnoreCase
pembanding:
final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");
System.out.println(languages); // [c++, java, python]
Ketika saya mencoba untuk menghapus elemen-elemen tepat yang ada di TreeSet
, ia berfungsi: semua yang ditentukan dihapus:
languages.removeAll(Arrays.asList("PYTHON", "C++"));
System.out.println(languages); // [java]
Namun, jika saya mencoba untuk menghapus alih-alih lebih dari yang ada di dalam TreeSet
, panggilan itu tidak menghapus apa-apa sama sekali (ini bukan panggilan berikutnya tetapi disebut bukan potongan di atas):
languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));
System.out.println(languages); // [c++, java, python]
Apa yang saya lakukan salah? Mengapa itu berlaku seperti ini?
Sunting: String::compareToIgnoreCase
adalah pembanding yang valid:
(l, r) -> l.compareToIgnoreCase(r)
Jawaban:
Inilah javadoc dari removeAll () :
Dalam percobaan kedua Anda, Anda berada di javadoc kasus pertama. Jadi iterates lebih dari "java", "c ++", dll dan memeriksa apakah mereka terkandung dalam Set dikembalikan oleh
Set.of("PYTHON", "C++")
. Mereka tidak, jadi mereka tidak dihapus. Gunakan TreeSet lain menggunakan pembanding yang sama dengan argumen, dan itu akan berfungsi dengan baik. Menggunakan dua implementasi Set yang berbeda, satu menggunakanequals()
, dan yang lainnya menggunakan komparator, memang berbahaya untuk dilakukan.Perhatikan bahwa ada bug yang dibuka tentang ini: [JDK-8180409] TreeSet menghapus semua perilaku tidak konsisten dengan String.CASE_INSENSITIVE_ORDER .
sumber
final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase);
subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP"));
languages.removeAll(subLanguages);
TreeSet
.