JDK-6396943 : TreeSet, TreeMap removeAll() method uses Comparator inconsistently
  • Type: Bug
  • Component: core-libs
  • Sub-Component: java.util:collections
  • Affected Version: 6
  • Priority: P4
  • Status: Closed
  • Resolution: Duplicate
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2006-03-10
  • Updated: 2021-03-03
  • Resolved: 2006-03-10
Related Reports
Duplicate :  
Description
FULL PRODUCT VERSION :
java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

also

java version "1.6.0-beta2"
Java(TM) SE Runtime Environment (build 1.6.0-beta2-b75)
Java HotSpot(TM) Client VM (build 1.6.0-beta2-b75, mixed mode)

ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows 2000 [Version 5.00.2195]

A DESCRIPTION OF THE PROBLEM :
TreeSet.removeAll() uses Comparator sometimes and equals() at other times. It should use the same thing all the time, so the behaviour is consistent.

  See also: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4730113

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Create a TreeSet T and an ArrayList Y. call remove() on the TreeSet using the ArrayList as a parameter. If T.size() < Y.size(), then the Comparator is used. Otherwise the ArrayList's contains() method is used (which uses equals()). The TreeSet should either use its own contains() method all the time or the parameter collection's contains() method all the time, not a little of each.

Please use the JVM flag -enableassertions when running the test case to see the failure:



EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
No failure.

This test case should either fail on the first assert or not at all. The behaviour of removeAll() should not depend on the size of the collection being removed.

ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.lang.AssertionError
        at TreeSetTest.main(TreeSetTest.java:21)

REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.util.*;

public class TreeSetTest {

    public static void main(String[] args) {
        SortedSet set;

        set = new TreeSet(String.CASE_INSENSITIVE_ORDER);
        set.addAll(Arrays.asList("a", "b", "c"));
        set.removeAll(Arrays.asList("A"));
        assert(2 == set.size());

        set = new TreeSet(String.CASE_INSENSITIVE_ORDER);
        set.addAll(Arrays.asList("a", "b", "c"));
        set.removeAll(Arrays.asList("A", "B"));
        assert(1 == set.size());

        set = new TreeSet(String.CASE_INSENSITIVE_ORDER);
        set.addAll(Arrays.asList("a", "b", "c"));
        set.removeAll(Arrays.asList("A", "B", "C"));
        assert(0 == set.size());
    }
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
Loop through the removed elements and call remove() one at a time.

Comments
EVALUATION This appears to be a dup of 6394757: (coll) AbstractSet.removeAll is surprisingly dependent on relative collection sizes Why all this interest now? This was introduced in 1.3.
10-03-2006