커스텀 비교기를 사용하여 TreeSet에서 제거하지 않는 이유는 무엇입니까?


22

Java 8과 Java 11을 모두 사용 TreeSet하여 String::compareToIgnoreCase비교기를 사용 하여 다음 을 고려하십시오 .

final Set<String> languages = new TreeSet<>(String::compareToIgnoreCase);
languages.add("java");
languages.add("c++");
languages.add("python");

System.out.println(languages);                 // [c++, java, python]

에있는 정확한 요소를 제거하려고 TreeSet하면 작동합니다. 지정된 모든 요소 가 제거됩니다.

languages.removeAll(Arrays.asList("PYTHON", "C++"));

System.out.println(languages);                 // [java]

내가 대신 제거하려고하는 경우에는 에 존재하는 것보다 TreeSet, 전화 (이것은 후속 호출하지 않고 대신 조각 위의 부르심을) 전혀 아무것도 제거하지 않습니다 :

languages.removeAll(Arrays.asList("PYTHON", "C++", "LISP"));

System.out.println(languages);                 // [c++, java, python]

내가 무엇을 잘못하고 있지? 왜 이런 식으로 행동합니까?

편집 : String::compareToIgnoreCase유효한 비교기입니다.

(l, r) -> l.compareToIgnoreCase(r)

5
관련 버그 입력 : bugs.openjdk.java.net/browse/JDK-8180409 (TreeSet removeString.CASE_INSENSITIVE_ORDER 와 일치하지 않는 모든 동작)
Progman

(A)는 밀접하게 관련된 Q & A .
Naman

답변:


22

다음은 removeAll () 의 javadoc입니다 .

이 구현은 각각에 대해 size 메소드를 호출하여이 세트와 지정된 콜렉션 중 작은 것을 결정합니다. 이 세트에 요소가 적은 경우, 구현은이 세트에 대해 반복되어, 반복자에 의해 돌려 주어진 각 요소가 차례로 지정된 컬렉션에 포함되어 있는지 확인합니다. 포함 된 경우 반복자의 remove 메소드를 사용하여이 세트에서 제거됩니다. 지정된 컬렉션에 요소가 적은 경우, 구현은 지정된 컬렉션을 반복하고,이 세트의 remove 메소드를 사용해, 반복자에 의해 돌려 주어진 각 요소를이 세트로부터 삭제합니다.

두 번째 실험에서는 javadoc의 첫 번째 경우입니다. 따라서 "java", "c ++"등을 반복하여에 의해 반환 된 Set에 포함되어 있는지 확인합니다 Set.of("PYTHON", "C++"). 그것들은 제거되지 않았습니다. 인수와 동일한 비교자를 사용하여 다른 TreeSet을 사용하면 정상적으로 작동합니다. 하나는를 사용 equals()하고 다른 하나는 비교자를 사용하는 두 가지 다른 Set 구현을 사용하는 것은 실제로 위험한 일입니다.

참고 이것에 대해 열린 버그가 있다는 것을 : String.CASE_INSENSITIVE_ORDER와 [JDK-8180409] TreeSet의에서 removeAll 일관성없는 행동 .


두 세트가 동일한 특성을 가질 때 작동합니까? final Set<String> subLanguages = new TreeSet<>(String::compareToIgnoreCase); subLanguages.addAll(Arrays.asList("PYTHON", "C++", "LISP")); languages.removeAll(subLanguages);
Nikolas

1
javadoc에 설명 된 "이 세트에 요소가 더 적은 경우"가 있습니다. 다른 경우는 "지정된 컬렉션에 요소가 더 적은 경우"입니다.
JB 니 제트

8
이 답변은 옳지 만 매우 직관적이지 않은 행동입니다. 의 디자인에 결함이있는 것 같습니다 TreeSet.
Boann

나는 동의하지만 그것에 대해 아무것도 할 수 없습니다.
JB 니 제트

4
둘 다입니다 : 그것은 정확하게 문서화 된 매우 직관적이지 않은 행동이지만, 직관적이지 않고 속이는 것은 언젠가는 고칠 수있는 디자인 버그이기도합니다.
JB 니 제트
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.