This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git


The following commit(s) were added to refs/heads/master by this push:
     new bd76c28  Add removeIf (#70)
bd76c28 is described below

commit bd76c282598967655d12697b6b1aba90b1da735b
Author: 이종현 <[email protected]>
AuthorDate: Sun May 5 23:16:38 2019 +0900

    Add removeIf (#70)
    
    * Add removeIf to SynchronizedCollection, Add mac store files to gitignore
    
    * - added removeIf
    
    * - added removeIf
    - added Tests for removeIf
    
    * minor fix
    
    * p tag fix in comments
    
    * Added @since 4.4 javadoc tag
---
 .gitignore                                         |  3 +
 .../commons/collections4/bag/UnmodifiableBag.java  |  9 +++
 .../collections4/bag/UnmodifiableSortedBag.java    |  9 +++
 .../collections4/bidimap/AbstractDualBidiMap.java  | 23 ++++++++
 .../collection/AbstractCollectionDecorator.java    |  9 +++
 .../collection/CompositeCollection.java            | 42 +++++++++++---
 .../collections4/collection/IndexedCollection.java | 25 ++++++++
 .../collection/SynchronizedCollection.java         | 11 ++++
 .../collection/UnmodifiableBoundedCollection.java  |  9 +++
 .../collection/UnmodifiableCollection.java         |  9 +++
 .../commons/collections4/list/FixedSizeList.java   |  9 +++
 .../commons/collections4/list/SetUniqueList.java   | 11 ++++
 .../collections4/list/UnmodifiableList.java        |  9 +++
 .../apache/commons/collections4/map/LinkedMap.java |  9 +++
 .../collections4/map/UnmodifiableEntrySet.java     |  9 +++
 .../multiset/UnmodifiableMultiSet.java             |  9 +++
 .../collections4/queue/UnmodifiableQueue.java      |  9 +++
 .../commons/collections4/set/CompositeSet.java     | 17 ++++++
 .../commons/collections4/set/ListOrderedSet.java   | 17 ++++++
 .../commons/collections4/set/MapBackedSet.java     |  9 +++
 .../collections4/set/UnmodifiableNavigableSet.java |  9 +++
 .../commons/collections4/set/UnmodifiableSet.java  |  9 +++
 .../collections4/set/UnmodifiableSortedSet.java    |  9 +++
 .../collection/AbstractCollectionTest.java         | 66 ++++++++++++++++++++++
 .../collection/CompositeCollectionTest.java        | 23 ++++++++
 25 files changed, 364 insertions(+), 9 deletions(-)

diff --git a/.gitignore b/.gitignore
index 338a65b..6ff3feb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -15,3 +15,6 @@ site-content
 .settings
 .classpath
 .project
+
+# Mac files
+.DS_Store
\ No newline at end of file
diff --git 
a/src/main/java/org/apache/commons/collections4/bag/UnmodifiableBag.java 
b/src/main/java/org/apache/commons/collections4/bag/UnmodifiableBag.java
index 9100a61..1f22f70 100644
--- a/src/main/java/org/apache/commons/collections4/bag/UnmodifiableBag.java
+++ b/src/main/java/org/apache/commons/collections4/bag/UnmodifiableBag.java
@@ -22,6 +22,7 @@ import java.io.ObjectOutputStream;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Bag;
 import org.apache.commons.collections4.Unmodifiable;
@@ -128,6 +129,14 @@ public final class UnmodifiableBag<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java 
b/src/main/java/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java
index c07e134..b7ced38 100644
--- 
a/src/main/java/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java
+++ 
b/src/main/java/org/apache/commons/collections4/bag/UnmodifiableSortedBag.java
@@ -22,6 +22,7 @@ import java.io.ObjectOutputStream;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.SortedBag;
 import org.apache.commons.collections4.Unmodifiable;
@@ -125,6 +126,14 @@ public final class UnmodifiableSortedBag<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
 
b/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
index 7f338f8..eb9c96b 100644
--- 
a/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
+++ 
b/src/main/java/org/apache/commons/collections4/bidimap/AbstractDualBidiMap.java
@@ -20,6 +20,8 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.BidiMap;
 import org.apache.commons.collections4.MapIterator;
@@ -370,6 +372,27 @@ public abstract class AbstractDualBidiMap<K, V> implements 
BidiMap<K, V> {
             return decorated().hashCode();
         }
 
+        /**
+         * @since 4.4
+         */
+        @Override
+        public boolean removeIf(Predicate<? super E> filter) {
+            if (parent.isEmpty() || Objects.isNull(filter)) {
+                return false;
+            }
+            boolean modified = false;
+            final Iterator<?> it = iterator();
+            while (it.hasNext()) {
+                @SuppressWarnings("unchecked")
+                final E e = (E) it.next();
+                if (filter.test(e)) {
+                    it.remove();
+                    modified = true;
+                }
+            }
+            return modified;
+        }
+
         @Override
         public boolean removeAll(final Collection<?> coll) {
             if (parent.isEmpty() || coll.isEmpty()) {
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
 
b/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
index 95846e2..f38759c 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/AbstractCollectionDecorator.java
@@ -19,6 +19,7 @@ package org.apache.commons.collections4.collection;
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.function.Predicate;
 
 /**
  * Decorates another <code>Collection</code> to provide additional behaviour.
@@ -159,6 +160,14 @@ public abstract class AbstractCollectionDecorator<E>
         return decorated().containsAll(coll);
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        return decorated().removeIf(filter);
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         return decorated().removeAll(coll);
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
index 6214017..1f41be2 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/CompositeCollection.java
@@ -22,6 +22,8 @@ import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.iterators.EmptyIterator;
@@ -34,7 +36,7 @@ import org.apache.commons.collections4.list.UnmodifiableList;
  * Changes made to this collection will actually be made on the decorated 
collection.
  * Add and remove operations require the use of a pluggable strategy. If no
  * strategy is provided then add and remove are unsupported.
- *
+ * </p>
  * @param <E> the type of the elements in the collection
  * @since 3.0
  */
@@ -93,7 +95,7 @@ public class CompositeCollection<E> implements Collection<E>, 
Serializable {
      * Gets the size of this composite collection.
      * <p>
      * This implementation calls <code>size()</code> on each collection.
-     *
+     * </p>
      * @return total number of elements in all contained containers
      */
     @Override
@@ -109,7 +111,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * Checks whether this composite collection is empty.
      * <p>
      * This implementation calls <code>isEmpty()</code> on each collection.
-     *
+     * </p>
      * @return true if all of the contained collections are empty
      */
     @Override
@@ -126,7 +128,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * Checks whether this composite collection contains the object.
      * <p>
      * This implementation calls <code>contains()</code> on each collection.
-     *
+     * </p>
      * @param obj  the object to search for
      * @return true if obj is contained in any of the contained collections
      */
@@ -144,7 +146,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * Gets an iterator over all the collections in this composite.
      * <p>
      * This implementation uses an <code>IteratorChain</code>.
-     *
+     * </p>
      * @return an <code>IteratorChain</code> instance which supports
      *  <code>remove()</code>. Iteration occurs over contained collections in
      *  the order they were added, but this behavior should not be relied upon.
@@ -254,7 +256,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * <p>
      * This implementation calls <code>contains()</code> for each element in 
the
      * specified collection.
-     *
+     * </p>
      * @param coll  the collection to check for
      * @return true if all elements contained
      */
@@ -296,7 +298,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * Removes the elements in the specified collection from this composite 
collection.
      * <p>
      * This implementation calls <code>removeAll</code> on each collection.
-     *
+     * </p>
      * @param coll  the collection to remove
      * @return true if the collection was modified
      * @throws UnsupportedOperationException if removeAll is unsupported
@@ -314,11 +316,33 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
     }
 
     /**
+     * Removes all of the elements of this collection that satisfy the given 
predicate from this composite collection.
+     * <p>
+     * This implementation calls <code>removeIf</code> on each collection.
+     * </p>
+     * @param filter  a predicate which returns true for elements to be removed
+     * @return true if the collection was modified
+     * @throws UnsupportedOperationException if removeIf is unsupported
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        if (Objects.isNull(filter)) {
+            return false;
+        }
+        boolean changed = false;
+        for (final Collection<E> item : all) {
+            changed |= item.removeIf(filter);
+        }
+        return changed;
+    }
+
+    /**
      * Retains all the elements in the specified collection in this composite 
collection,
      * removing all others.
      * <p>
      * This implementation calls <code>retainAll()</code> on each collection.
-     *
+     * </p>
      * @param coll  the collection to remove
      * @return true if the collection was modified
      * @throws UnsupportedOperationException if retainAll is unsupported
@@ -338,7 +362,7 @@ public class CompositeCollection<E> implements 
Collection<E>, Serializable {
      * Removes all of the elements from this collection .
      * <p>
      * This implementation calls <code>clear()</code> on each collection.
-     *
+     * </p>
      * @throws UnsupportedOperationException if clear is unsupported
      */
     @Override
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/IndexedCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/IndexedCollection.java
index 95acfc9..04bcc88 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/IndexedCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/IndexedCollection.java
@@ -18,6 +18,9 @@ package org.apache.commons.collections4.collection;
 
 import java.util.Collection;
 import java.util.HashMap;
+import java.util.Iterator;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.MultiMap;
 import org.apache.commons.collections4.Transformer;
@@ -212,6 +215,28 @@ public class IndexedCollection<K, C> extends 
AbstractCollectionDecorator<C> {
         return removed;
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super C> filter) {
+        if (Objects.isNull(filter)) {
+            return false;
+        }
+        boolean changed = false;
+        final Iterator<C> it = iterator();
+        while (it.hasNext()) {
+            if (filter.test(it.next())) {
+                it.remove();
+                changed = true;
+            }
+        }
+        if (changed) {
+            reindex();
+        }
+        return changed;
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         boolean changed = false;
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/SynchronizedCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/SynchronizedCollection.java
index 39d2daf..b76e387 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/SynchronizedCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/SynchronizedCollection.java
@@ -19,6 +19,7 @@ package org.apache.commons.collections4.collection;
 import java.io.Serializable;
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.function.Predicate;
 
 /**
  * Decorates another {@link Collection} to synchronize its behaviour
@@ -183,6 +184,16 @@ public class SynchronizedCollection<E> implements 
Collection<E>, Serializable {
         }
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        synchronized (lock) {
+            return decorated().removeIf(filter);
+        }
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         synchronized (lock) {
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java
index 837c1ee..9d06615 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/UnmodifiableBoundedCollection.java
@@ -18,6 +18,7 @@ package org.apache.commons.collections4.collection;
 
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.BoundedCollection;
 import org.apache.commons.collections4.Unmodifiable;
@@ -138,6 +139,14 @@ public final class UnmodifiableBoundedCollection<E> 
extends AbstractCollectionDe
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/collection/UnmodifiableCollection.java
 
b/src/main/java/org/apache/commons/collections4/collection/UnmodifiableCollection.java
index abf2984..99902fb 100644
--- 
a/src/main/java/org/apache/commons/collections4/collection/UnmodifiableCollection.java
+++ 
b/src/main/java/org/apache/commons/collections4/collection/UnmodifiableCollection.java
@@ -18,6 +18,7 @@ package org.apache.commons.collections4.collection;
 
 import java.util.Collection;
 import java.util.Iterator;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -97,6 +98,14 @@ public final class UnmodifiableCollection<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/list/FixedSizeList.java 
b/src/main/java/org/apache/commons/collections4/list/FixedSizeList.java
index bca2e46..4f9059a 100644
--- a/src/main/java/org/apache/commons/collections4/list/FixedSizeList.java
+++ b/src/main/java/org/apache/commons/collections4/list/FixedSizeList.java
@@ -20,6 +20,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.BoundedCollection;
 import org.apache.commons.collections4.iterators.AbstractListIteratorDecorator;
@@ -138,6 +139,14 @@ public class FixedSizeList<E>
         throw unsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw unsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw unsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java 
b/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java
index bbf16e0..2eb4421 100644
--- a/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java
+++ b/src/main/java/org/apache/commons/collections4/list/SetUniqueList.java
@@ -24,6 +24,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.ListUtils;
 import org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
@@ -242,6 +243,16 @@ public class SetUniqueList<E> extends 
AbstractSerializableListDecorator<E> {
         return result;
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        boolean result = super.removeIf(filter);
+        set.removeIf(filter);
+        return result;
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         boolean result = false;
diff --git 
a/src/main/java/org/apache/commons/collections4/list/UnmodifiableList.java 
b/src/main/java/org/apache/commons/collections4/list/UnmodifiableList.java
index be496c1..72c480e 100644
--- a/src/main/java/org/apache/commons/collections4/list/UnmodifiableList.java
+++ b/src/main/java/org/apache/commons/collections4/list/UnmodifiableList.java
@@ -20,6 +20,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -97,6 +98,14 @@ public final class UnmodifiableList<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git a/src/main/java/org/apache/commons/collections4/map/LinkedMap.java 
b/src/main/java/org/apache/commons/collections4/map/LinkedMap.java
index 5454bc8..26dff3b 100644
--- a/src/main/java/org/apache/commons/collections4/map/LinkedMap.java
+++ b/src/main/java/org/apache/commons/collections4/map/LinkedMap.java
@@ -26,6 +26,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Map;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
 import org.apache.commons.collections4.iterators.UnmodifiableListIterator;
@@ -262,6 +263,14 @@ public class LinkedMap<K, V> extends AbstractLinkedMap<K, 
V> implements Serializ
             throw new UnsupportedOperationException();
         }
 
+        /**
+         * @since 4.4
+         */
+        @Override
+        public boolean removeIf(final Predicate<? super K> filter) {
+            throw new UnsupportedOperationException();
+        }
+
         @Override
         public boolean removeAll(final Collection<?> coll) {
             throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/map/UnmodifiableEntrySet.java 
b/src/main/java/org/apache/commons/collections4/map/UnmodifiableEntrySet.java
index 9f9fccd..d98ba86 100644
--- 
a/src/main/java/org/apache/commons/collections4/map/UnmodifiableEntrySet.java
+++ 
b/src/main/java/org/apache/commons/collections4/map/UnmodifiableEntrySet.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.AbstractIteratorDecorator;
@@ -92,6 +93,14 @@ public final class UnmodifiableEntrySet<K, V>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super Map.Entry<K, V>> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/multiset/UnmodifiableMultiSet.java
 
b/src/main/java/org/apache/commons/collections4/multiset/UnmodifiableMultiSet.java
index 069978c..2a47efb 100644
--- 
a/src/main/java/org/apache/commons/collections4/multiset/UnmodifiableMultiSet.java
+++ 
b/src/main/java/org/apache/commons/collections4/multiset/UnmodifiableMultiSet.java
@@ -22,6 +22,7 @@ import java.io.ObjectOutputStream;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.MultiSet;
 import org.apache.commons.collections4.Unmodifiable;
@@ -125,6 +126,14 @@ public final class UnmodifiableMultiSet<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/queue/UnmodifiableQueue.java 
b/src/main/java/org/apache/commons/collections4/queue/UnmodifiableQueue.java
index 0963a19..621a33e 100644
--- a/src/main/java/org/apache/commons/collections4/queue/UnmodifiableQueue.java
+++ b/src/main/java/org/apache/commons/collections4/queue/UnmodifiableQueue.java
@@ -22,6 +22,7 @@ import java.io.ObjectOutputStream;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Queue;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -123,6 +124,14 @@ public final class UnmodifiableQueue<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/set/CompositeSet.java 
b/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
index 4ba7357..49d260c 100644
--- a/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
+++ b/src/main/java/org/apache/commons/collections4/set/CompositeSet.java
@@ -24,6 +24,8 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.iterators.EmptyIterator;
@@ -284,6 +286,21 @@ public class CompositeSet<E> implements Set<E>, 
Serializable {
     }
 
     /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        if (Objects.isNull(filter)) {
+            return false;
+        }
+        boolean changed = false;
+        for (final Collection<E> item : all) {
+            changed |= item.removeIf(filter);
+        }
+        return changed;
+    }
+
+    /**
      * Removes the elements in the specified collection from this composite 
set.
      * <p>
      * This implementation calls <code>removeAll</code> on each collection.
diff --git 
a/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java 
b/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java
index 5b87bca..b528915 100644
--- a/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java
+++ b/src/main/java/org/apache/commons/collections4/set/ListOrderedSet.java
@@ -23,6 +23,8 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import java.util.Set;
+import java.util.Objects;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.CollectionUtils;
 import org.apache.commons.collections4.OrderedIterator;
@@ -216,6 +218,21 @@ public class ListOrderedSet<E>
         return result;
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(final Predicate<? super E> filter) {
+        if (Objects.isNull(filter)) {
+            return false;
+        }
+        final boolean result = decorated().removeIf(filter);
+        if (result) {
+            setOrder.removeIf(filter);
+        }
+        return result;
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         boolean result = false;
diff --git 
a/src/main/java/org/apache/commons/collections4/set/MapBackedSet.java 
b/src/main/java/org/apache/commons/collections4/set/MapBackedSet.java
index 6e246a5..0aab264 100644
--- a/src/main/java/org/apache/commons/collections4/set/MapBackedSet.java
+++ b/src/main/java/org/apache/commons/collections4/set/MapBackedSet.java
@@ -21,6 +21,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.Map;
 import java.util.Set;
+import java.util.function.Predicate;
 
 /**
  * Decorates a <code>Map</code> to obtain <code>Set</code> behaviour.
@@ -142,6 +143,14 @@ public final class MapBackedSet<E, V> implements Set<E>, 
Serializable {
         return map.size() != size;
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        return map.keySet().removeIf(filter);
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         return map.keySet().removeAll(coll);
diff --git 
a/src/main/java/org/apache/commons/collections4/set/UnmodifiableNavigableSet.java
 
b/src/main/java/org/apache/commons/collections4/set/UnmodifiableNavigableSet.java
index 3b309e1..7064701 100644
--- 
a/src/main/java/org/apache/commons/collections4/set/UnmodifiableNavigableSet.java
+++ 
b/src/main/java/org/apache/commons/collections4/set/UnmodifiableNavigableSet.java
@@ -23,6 +23,7 @@ import java.util.Collection;
 import java.util.Iterator;
 import java.util.NavigableSet;
 import java.util.SortedSet;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -94,6 +95,14 @@ public final class UnmodifiableNavigableSet<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/set/UnmodifiableSet.java 
b/src/main/java/org/apache/commons/collections4/set/UnmodifiableSet.java
index 022c9dc..79a9a9b 100644
--- a/src/main/java/org/apache/commons/collections4/set/UnmodifiableSet.java
+++ b/src/main/java/org/apache/commons/collections4/set/UnmodifiableSet.java
@@ -19,6 +19,7 @@ package org.apache.commons.collections4.set;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.Set;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -96,6 +97,14 @@ public final class UnmodifiableSet<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/main/java/org/apache/commons/collections4/set/UnmodifiableSortedSet.java 
b/src/main/java/org/apache/commons/collections4/set/UnmodifiableSortedSet.java
index 6a60e8c..0a129cf 100644
--- 
a/src/main/java/org/apache/commons/collections4/set/UnmodifiableSortedSet.java
+++ 
b/src/main/java/org/apache/commons/collections4/set/UnmodifiableSortedSet.java
@@ -22,6 +22,7 @@ import java.io.ObjectOutputStream;
 import java.util.Collection;
 import java.util.Iterator;
 import java.util.SortedSet;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.Unmodifiable;
 import org.apache.commons.collections4.iterators.UnmodifiableIterator;
@@ -96,6 +97,14 @@ public final class UnmodifiableSortedSet<E>
         throw new UnsupportedOperationException();
     }
 
+    /**
+     * @since 4.4
+     */
+    @Override
+    public boolean removeIf(Predicate<? super E> filter) {
+        throw new UnsupportedOperationException();
+    }
+
     @Override
     public boolean removeAll(final Collection<?> coll) {
         throw new UnsupportedOperationException();
diff --git 
a/src/test/java/org/apache/commons/collections4/collection/AbstractCollectionTest.java
 
b/src/test/java/org/apache/commons/collections4/collection/AbstractCollectionTest.java
index c181309..e62d942 100644
--- 
a/src/test/java/org/apache/commons/collections4/collection/AbstractCollectionTest.java
+++ 
b/src/test/java/org/apache/commons/collections4/collection/AbstractCollectionTest.java
@@ -33,6 +33,7 @@ import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
 import java.util.NoSuchElementException;
+import java.util.function.Predicate;
 
 import org.apache.commons.collections4.AbstractObjectTest;
 
@@ -945,6 +946,53 @@ public abstract class AbstractCollectionTest<E> extends 
AbstractObjectTest {
     }
 
     /**
+     *  Tests {@link Collection#removeIf(Predicate)}.
+     * @since 4.4
+     */
+    public void testCollectionRemoveIf() {
+        if (!isRemoveSupported()) {
+            return;
+        }
+
+        resetEmpty();
+        assertTrue("Empty collection removeIf should return false for a 
predicate that returns only false",
+                !getCollection().removeIf(e -> false));
+        verify();
+
+        assertTrue("Empty collection removeIf should return false for a 
predicate that returns only true",
+                !getCollection().removeIf(e -> true));
+        verify();
+
+        resetFull();
+        assertTrue("Full collection removeIf should return false for a 
predicate that returns only false",
+                !getCollection().removeIf(e -> false));
+        verify();
+
+        assertTrue("Full collection removeIf should return true for a 
predicate that returns only true",
+                getCollection().removeIf(e -> true));
+        getConfirmed().removeIf(e -> true);
+        verify();
+
+        resetFull();
+        final List<E> elements = Arrays.asList(getFullElements());
+
+        final int mid = getFullElements().length / 2;
+        final E target = elements.get(mid);
+
+        final int size = getCollection().size();
+        final int targetCount = Collections.frequency(elements, target);
+
+        final Predicate<E> filter = e -> target.equals((E) e);
+
+        assertTrue("Full collection removeIf should work", 
getCollection().removeIf(filter));
+        getConfirmed().removeIf(filter);
+        verify();
+
+        assertTrue("Collection should shrink after removeIf", 
getCollection().size() == size - targetCount);
+        assertTrue("Collection shouldn't contain removed element", 
!getCollection().contains(target));
+    }
+
+    /**
      *  Tests {@link Collection#retainAll(Collection)}.
      */
     public void testCollectionRetainAll() {
@@ -1159,6 +1207,14 @@ public abstract class AbstractCollectionTest<E> extends 
AbstractObjectTest {
         verify();
 
         try {
+            getCollection().removeIf(e -> true);
+            fail("removeIf should raise UnsupportedOperationException");
+        } catch (final UnsupportedOperationException e) {
+            // expected
+        }
+        verify();
+
+        try {
             getCollection().removeAll(null);
             fail("removeAll should raise UnsupportedOperationException");
         } catch (final UnsupportedOperationException e) {
@@ -1251,6 +1307,16 @@ public abstract class AbstractCollectionTest<E> extends 
AbstractObjectTest {
         resetFull();
         try {
             final Iterator<E> iter = getCollection().iterator();
+            getCollection().removeIf(e -> false);
+            iter.next();
+            fail("next after removeIf should raise ConcurrentModification");
+        } catch (final ConcurrentModificationException e) {
+            // expected
+        }
+
+        resetFull();
+        try {
+            final Iterator<E> iter = getCollection().iterator();
             final List<E> sublist = 
Arrays.asList(getFullElements()).subList(2,5);
             getCollection().removeAll(sublist);
             iter.next();
diff --git 
a/src/test/java/org/apache/commons/collections4/collection/CompositeCollectionTest.java
 
b/src/test/java/org/apache/commons/collections4/collection/CompositeCollectionTest.java
index 8cdc920..c3ad0d5 100644
--- 
a/src/test/java/org/apache/commons/collections4/collection/CompositeCollectionTest.java
+++ 
b/src/test/java/org/apache/commons/collections4/collection/CompositeCollectionTest.java
@@ -22,6 +22,7 @@ import java.util.Collection;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
+import java.util.function.Predicate;
 
 import org.junit.Assert;
 
@@ -345,6 +346,28 @@ public class CompositeCollectionTest<E> extends 
AbstractCollectionTest<E> {
         assertTrue(!two.contains("1"));
     }
 
+    /**
+     * @since 4.4
+     */
+    @SuppressWarnings("unchecked")
+    public void testRemoveIf() {
+        setUpMutatorTest();
+        one.add((E) "1");
+        two.add((E) "2");
+        two.add((E) "1");
+        // need separate list to remove, as otherwise one clears itself
+        final Predicate<E> predicate = e -> e == "1";
+        c.addComposited(one, two);
+        c.removeIf(predicate);
+        assertTrue(!c.contains("1"));
+        assertTrue(!one.contains("1"));
+        assertTrue(!two.contains("1"));
+        c.removeIf(null);
+        assertTrue(!c.contains("1"));
+        assertTrue(!one.contains("1"));
+        assertTrue(!two.contains("1"));
+    }
+
     @SuppressWarnings("unchecked")
     public void testRemoveComposited() {
         setUpMutatorTest();

Reply via email to