🌐
GeeksforGeeks
geeksforgeeks.org β€Ί java β€Ί set-removeall-method-in-java-with-examples
Set removeAll() Method in Java - GeeksforGeeks
July 11, 2025 - Example 1: This example demonstrates how the removeAll() method removes all elements from the first set that are also present in the second set. ... // Java Program to demosntrates // the working of Set removeAll() import java.util.HashSet; import java.util.Set; public class Geeks { public static void main(String[] args) { // Adding elements in the first set Set<String> s1 = new HashSet<>(); s1.add("Geek1"); s1.add("Geek2"); s1.add("Geek3"); s1.add("Geek4"); // Adding elements in the second set Set<String> s2 = new HashSet<>(); s2.add("Geek3"); s2.add("Geek4"); System.out.println("Set1 before removeAll(): " + s1); // Remove all elements of s2 from s1 s1.removeAll(s2); System.out.println("Set1 after removeAll(): " + s1); } }
🌐
Tabnine
tabnine.com β€Ί home β€Ί code library
Code Library - Tabnine
July 25, 2024 - Get the answers and suggestions you need from our AI code assistant. Get started in minutes with a free 90 day trial of Tabnine Pro.
Discussions

java - Unintuitive behavior of removeAll method in sets - Stack Overflow
I discovered this weird behavior of the removeAll method of AbstractSets when working with individual Comparators. Depending on the size of the compared collections a different comparator is used.... More on stackoverflow.com
🌐 stackoverflow.com
java - ArrayList removeAll() not removing objects - Stack Overflow
Also when you override .equals it is recommended to also override hashCode so that the objects also work correctly in hashing functions like Set or Map. ... @TJCrowder also, do not forget to check if anObject is an instance of the class. More on stackoverflow.com
🌐 stackoverflow.com
java - AbstractSet.removeAll() method not working properly - Stack Overflow
This is specified many times around java documentation. ... Sign up to request clarification or add additional context in comments. ... This is an inconsistency in the implementation of TreeSet, bordering on the bug. The code will ignore custom comparator when the number of items in the collection that you pass to removeAll is greater than or equal to the number of items in the set... More on stackoverflow.com
🌐 stackoverflow.com
March 31, 2017
java - Set remove() function does not work - Stack Overflow
while working with my application I've encountered a problem while trying to remove object from the java collection ( Set pulled from database with EclipseLink ). The object which I want to remove ... More on stackoverflow.com
🌐 stackoverflow.com
🌐
Reddit
reddit.com β€Ί r/java β€Ί the hashset.removeall method is surprisingly slow (in some cases)
r/java on Reddit: The HashSet<T>.removeAll method is surprisingly slow (in some cases)
March 11, 2020 - Otherwise the definition of Set would be too constricted, which is against the idea of interfaces. ... Read the other comment dude. ... Calling u/s888marks. This is your area of expertise isn't it? ... He's already aware of this (https://bugs.openjdk.java.net/browse/JDK-6982173). This is 5 years old, not sure why it resurfaced. ... And that bug is 10 years old. Basically, fixing the issue would change documented behaviour. Rock and hard place. ... public boolean removeAll(Collection<?> c) { Objects.requireNonNull(c); boolean modified = false; if (size() > c.size()) { for (Iterator<?> i = c.iterator(); i.hasNext(); ) modified |= remove(i.next()); } else { for (Iterator<?> i = iterator(); i.hasNext(); ) { if (c.contains(i.next())) { i.remove(); modified = true; } } } return modified; }
🌐
Educative
educative.io β€Ί answers β€Ί what-is-the-setremoveall-method-in-java
What is the Set.removeAll() method in Java?
Line 34: We display the collection set3 that needs to be removed from the Set. Line 37: We call the removeAll() function to remove the collection from the Set.
🌐
JetBrains
jetbrains.com β€Ί help β€Ί inspectopedia β€Ί SlowAbstractSetRemoveAll.html
Call to 'set.removeAll(list)' may work slowly | Inspectopedia Documentation
Reports calls to java.util.Set.removeAll() with a java.util.List argument. Such a call can be slow when the size of the argument is greater than or equal to the size of the set, and the set is a subclass of java.util.AbstractSet. In this case, List.contains() is called for each element in the set, which will perform a linear search.
🌐
OpenRewrite
docs.openrewrite.org β€Ί recipe catalog β€Ί static analysis and remediation β€Ί replace `java.util.set#removeall(java.util.collection)` with `java.util.collection#foreach(set::remove)`
Replace `java.util.Set#removeAll(java.util.Collection)` with `java.util.Collection#forEach(Set::remove)` | OpenRewrite Docs
Using java.util.Collection#forEach(Set::remove) rather than java.util.Set#removeAll(java.util.Collection) may improve performance due to a possible O(n^2) complexity. GitHub: UseForEachRemoveInsteadOfSetRemoveAll.java, Issue Tracker, Code Genome Project Β· This recipe is available under the Moderne Source Available License.
Published: 1 week ago
🌐
Stack Overflow
stackoverflow.com β€Ί questions β€Ί 18123178 β€Ί unintuitive-behavior-of-removeall-method-in-sets
java - Unintuitive behavior of removeAll method in sets - Stack Overflow
So when the Stack has more or the same number of elements than the TreeSet (happens in the first case), removeAll will iterate through the TreeSet and remove each element contained in the Stack. Since the Stack uses the default String compare, no strings will match, and nothing will be removed.
🌐
GeeksforGeeks
geeksforgeeks.org β€Ί java β€Ί hashset-removeall-method-in-java-with-example
HashSet removeAll() method in Java with Example - GeeksforGeeks
December 9, 2021 - Exception: This method throws NullPointerException if this set contains a null element and the specified collection does not permit null elements (optional), or if the specified collection is null. Below are the examples to illustrate the removeAll() method. Example 1: Java Β·
Find elsewhere
Top answer
1 of 3
6

You only read documentation partly. You forgot one important paragraph from TreeSet:

Note that the ordering maintained by a set (whether or not an explicit comparator is provided) must be consistent with equals if it is to correctly implement the Set interface. (See Comparable or Comparator for a precise definition of consistent with equals.) This is so because the Set interface is defined in terms of the equals operation, but a TreeSet instance performs all element comparisons using its compareTo (or compare) method, so two elements that are deemed equal by this method are, from the standpoint of the set, equal. The behavior of a set is well-defined even if its ordering is inconsistent with equals; it just fails to obey the general contract of the Set interface.

Now removeAll implementation comes from AbstractSet and utilizes equals method. According to your code you will have that "a".equals("A") is not true so that elements are not considered equal even if you provided a comparator which manages them when used in the TreeSet itself. If you try with a wrapper then the problem goes away:

import java.util.*;
import java.lang.*;

class Test
{
    static class StringWrapper implements Comparable<StringWrapper>
    {
      public final String string;

      public StringWrapper(String string)
      {
        this.string = string;
      }

      @Override public boolean equals(Object o)
      { 
        return o instanceof StringWrapper && 
            ((StringWrapper)o).string.compareToIgnoreCase(string) == 0; 
      }

      @Override public int compareTo(StringWrapper other) { 
        return string.compareToIgnoreCase(other.string); 
      }

      @Override public String toString() { return string; }
    }

    static void test(StringWrapper... abc) 
    {
        Set<StringWrapper> s = new TreeSet<>();
        s.addAll(Arrays.asList(new StringWrapper("a"), new StringWrapper("b")));
        s.removeAll(Arrays.asList(abc));
        System.out.println(s);
    }

    public static void main(String[] args)
    {
        test(new StringWrapper("A"));
        test(new StringWrapper("A"), new StringWrapper("C"));
    }
}

This because you are now providing a consistent implementation between equals and compareTo of your object so you never have incoherent behavior between how the objects are added inside the sorted set and how all the abstract behavior of the set uses them.

This is true in general, a sort of rule of three for Java code: if you implement compareTo or equals or hashCode you should always implement all of them to avoid problems with standard collections (even if hashCode is less crucial unless you are using these objects in any hashed collection). This is specified many times around java documentation.

2 of 3
3

This is an inconsistency in the implementation of TreeSet<E>, bordering on the bug. The code will ignore custom comparator when the number of items in the collection that you pass to removeAll is greater than or equal to the number of items in the set.

The inconsistency is caused by a small optimization: if you look at the implementation of removeAll, which is inherited from AbstractSet, the optimization goes as follows:

public boolean removeAll(Collection<?> c) {
    boolean modified = false;

    if (size() > c.size()) {
        for (Iterator<?> i = c.iterator(); i.hasNext(); )
            modified |= remove(i.next());
    } else {
        for (Iterator<?> i = iterator(); i.hasNext(); ) {
            if (c.contains(i.next())) {
                i.remove();
                modified = true;
            }
        }
    }
    return modified;
}

you can see that the behavior is different when c has fewer items than this set (top branch) vs. when it has as many or more items (bottom branch).

Top branch uses the comparator associated with this set, while the bottom branch uses equals for comparison c.contains(i.next()) - all in the same method!

You can demonstrate this behavior by adding a few extra elements to the original tree set:

s.addAll(Arrays.asList("x", "z", "a", "b"));

Now the output for both test cases becomes identical, because remove(i.next()) utilizes the comparator of the set.

🌐
Coderanch
coderanch.com β€Ί t β€Ί 371982 β€Ί java β€Ί HashSet-removeAll
HashSet and removeAll() (Java in General forum at Coderanch)
Optional 'thank-you' note: Send Β· I'm sorry - I figured this out already. I had incorrectly implemented the hashCode() method in my Test class. In some intances, Tests that should be considered equal were returning different hashCode values which was preventing the HashSet.removeAll() method from working correctly.
Top answer
1 of 2
6

A few possibilities:

1) There is a problem with the implementation of id's equals or hashCode methods. In this case, you could have id1.equals(id2) but id1.hashCode() != id2.hashCode(). This would cause inconsistency between equals and hashCode() for the album objects and could cause the symptoms you're seeing.

2) The id for one or more albums changes at some point after the for loop that checks deleteAlbum.equals(entity) for each album in the Set. If an id changes for an album, the remove() method may not be able to find it. An id could change from null to some non null number if got saved to the database - EclipseLink might do this for you without you explicitly asking it to.

3) Because of EclipseLink's meddling, deleteGroup might not actually be a HashSet when you run your code. The docs for EclipseLink suggest it will give you an "indirection object" instead of the java.util.Set (or java.util.HashSet I presume) declared in your class, depending on how it is configured. In that case, the contains and remove methods might not do what you expect them to.

See Overriding equals and hashCode in Java for more details on these and other possible problems involving equals and hashCode, which can cause bizarre behavior with Sets.

2 of 2
2

Okay let's try a bit of testing:

1:

Iterator<AlbumEntity> it = deleteGroup.getAlbums().iterator();    
while(it.hasNext()){
    AlbumEntity entity = it.next();
    Assert.assertTrue(deleteGroup.getAlbums().contains(entity))
}

Does this test run successfully?

🌐
Baeldung
baeldung.com β€Ί home β€Ί java β€Ί java collections β€Ί performance of removeall() in a hashset
Performance of removeAll() in a HashSet | Baeldung
January 8, 2024 - As a result, elements 1 and 3 will be removed from the set. The removeAll() method determines which one is smaller – the set or the collection.
Top answer
1 of 1
8

This is because you haven't overriden Object#hashCode() in your class.

The implementation of hashCode() in Object returns a value that is computed from the calling objects memory address . So unless you pass a reference to the object contained in the map that you'd like to remove using remove(Object o) then the HashSet won't be able to locate the Object.
NOTE: Reference is not the same as a equal object defined by o1.equals(o2)

See bottom of post for explanation as to why 'HashSet#contains(Object o)' still works even when Objects being stored in the map haven't overriden Object#hashCode()


Say I have a class MyClass that doesn't override hashCode()
MyClass instance1 = new MyClass(); // Memory Address = 0x01
MyClass instance2 = new MyClass(); // Memory Address = 0x02
instance1.equals(instance2) == false

I can add these unique objects to a HashSet no problems, as adding to a HashSet only relies on equals(Object o), not hashCode().

Now let's say I want to remove them from the Set but I lost my original references to them, I do have the following references though:
instance3 // Memory Address = 0x03
instance4 // Memory Address = 0x04
instance1.equals(instance3) == true
instance2.equals(instance4) == true

A call to nonHashSet.remove(instance3) will remove instance1 from the Set. But Hash Based Sets work completely different: the hashCode (value computed from the memory address since we used Object#hashCode()) is used to locate the item. So when I ask the HashSet to remove instance3 it tells me that there is no element at that hash index. This is because the memory address of instance1 and instance3 are different, thus the hash for each is different meaning.

This is really bad as now the only reliable ways to remove instance1 or instance2 from the set is to clear the whole set or of course reinitialise it.


What happens under the hood in a HashSet:

When you attempt to add an element first the HashSet checks if another element considered equal to the element being added is already contained. If the element being added is unique to all other elements, it is added to the set.

How a HashSet differs from say a NonHashSet is how the elements are stored and retrieved.

In a HashSet, after an element is added to the set (as in when add(E element) returns true) a hash of that element is produced by calling element.hashCode(). In very loose terms you can think of the hash as the index that the element will be stored at.

Retrieved from https://en.wikipedia.org/wiki/Hash_table

Where key == element, hash function == element.hashCode(), buckets == indexes in the way I described it above

A note regarding Buckets: unlike traditional storage where each element gets its own index, it's not uncommon for two different elements (not considered equal to each other) to produce the same hash. When this happens a collision handling mechanism is used to store elements that have the same hash. This is beyond the scope of this question, but a common and simple way to handle this is to make a List at the collision hash index that stores all elements that contain the same hash.

When removing an element from a hash based set, the element that we are passing as the argument to be removed has it's hash calculated, then that hash is used to locate the element. If there is more than one element at the hash index (occurs when there are elements that have the same hash) then the collision handling mechanism the HashSet uses is used to find the exact item we are looking for. In the above specified mechanism (store a List at the collision index to store each collided element) elements.equals(collidedElement)

The general contract a hashCode() implementation should conform to: Hash Code Contract Java SE 8

Further information: Why do I need to override the equals and hashCode methods in Java?

Simple way to implement a EFFECTIVE hash function: Best implementation for hashCode method

How contains(Object o) Still Works:

Let's take a look at the code (Java Version 7u40-b43) that determines the return value ofcontains(Object o)in HashSet class. I've added comments to describe what is happening:

// contains(Object o) will return true if this method returns non-null
// NOTE: Entry<K,V> seems out of place as we are dealing with a Set not a 
//       Map. But in fact the backing structure for HashSet is a type of Map
final Entry<K,V> getEntry(Object key) {
        if (size == 0) { // Set is empty, search element can't be contained
            return null;
        }

        // Calculate the hash of the search key:
        // IF the search key == null --> hash = 0
        // ELSE calculate and assign the hashCode for key inside method 
        //      hash()
        int hash = (key == null) ? 0 : hash(key);

        // Start at hash calculated, after each iteration set e to be 
        // the element that comes after e  (defined by e.next field). Stop 
        // iterating when e is null
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            // IF (the hash calculated from the search key and the hash 
            //     calculated from this Entries key are equal AND
            //     this Entries key equals the search key) OR
            //    (search key != null AND the search key equals this Entries 
            //     key)
            // then return entry --> contains returns true
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
    }
🌐
Jsparrow
jsparrow.github.io β€Ί rules β€Ί replace-set-remove-all-with-for-each.html
Replace Set.removeAll With ForEach | jSparrow Documentation
Calling the method 'removeAll' on a Set with a List as invocation argument may lead to performance problems due to a possible O(n^2) complexity. This rule replaces such invocations. For example, the invocation 'mySet.removeAll(myList);' is replaced by 'myList.forEach(mySet::remove);'.
🌐
GeeksforGeeks
geeksforgeeks.org β€Ί java β€Ί abstractset-removeall-method-in-java-with-examples
AbstractSet removeAll() Method in Java - GeeksforGeeks
July 11, 2025 - AbstractSet before removeAll() operation: [1, 2, 3, 4, 5] Collection Elements to be removed: [1, 2, 3] AbstractSet after removeAll() operation: [4, 5] ... Parameters: This method takes collection c as a parameter containing elements to be removed from this set. Returns Value: This method returns true if this set changes as a result of the call. ... UnsupportedOperationException: This is thrown if the operation is not supported by this set.