diff --git a/src/main/java/org/apache/commons/collections4/SetUtils.java b/src/main/java/org/apache/commons/collections4/SetUtils.java
index 3d24cb271..f95a5e780 100644
--- a/src/main/java/org/apache/commons/collections4/SetUtils.java
+++ b/src/main/java/org/apache/commons/collections4/SetUtils.java
@@ -17,6 +17,7 @@
package org.apache.commons.collections4;
import java.util.AbstractSet;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
@@ -47,14 +48,56 @@ import org.apache.commons.collections4.set.UnmodifiableSortedSet;
public class SetUtils {
/**
- * Get a typed empty unmodifiable Set.
+ * An unmodifiable view of a set that may be backed by other sets.
+ *
+ * If the decorated sets change, this view will change as well. The contents
+ * of this view can be transferred to another instance via the {@link #copyInto(Set)}
+ * and {@link #toSet()} methods.
+ *
* @param the element type
- * @return an empty Set
+ * @since 4.1
*/
- public static Set emptySet() {
- return Collections.emptySet();
- }
+ public static abstract class SetView extends AbstractSet {
+ /**
+ * Copies the contents of this view into the provided set.
+ *
+ * @param the set type
+ * @param set the set for copying the contents
+ */
+ public > void copyInto(final S set) {
+ CollectionUtils.addAll(set, this);
+ }
+
+ /**
+ * Return an iterator for this view; the returned iterator is
+ * not required to be unmodifiable.
+ * @return a new iterator for this view
+ */
+ protected abstract Iterator createIterator();
+
+ @Override
+ public Iterator iterator() {
+ return IteratorUtils.unmodifiableIterator(createIterator());
+ }
+
+ @Override
+ public int size() {
+ return IteratorUtils.size(iterator());
+ }
+
+ /**
+ * Returns a new set containing the contents of this view.
+ *
+ * @return a new set containing all elements of this view
+ */
+ public Set toSet() {
+ final Set set = new HashSet<>(size());
+ copyInto(set);
+ return set;
+ }
+ }
+
/**
* An empty unmodifiable sorted set.
* This is not provided in the JDK.
@@ -63,410 +106,6 @@ public class SetUtils {
public static final SortedSet EMPTY_SORTED_SET =
UnmodifiableSortedSet.unmodifiableSortedSet(new TreeSet<>());
- /**
- * Get a typed empty unmodifiable sorted set.
- * @param the element type
- * @return an empty sorted Set
- */
- @SuppressWarnings("unchecked") // empty set is OK for any type
- public static SortedSet emptySortedSet() {
- return EMPTY_SORTED_SET;
- }
-
- /**
- * SetUtils
should not normally be instantiated.
- */
- private SetUtils() {}
-
- //-----------------------------------------------------------------------
-
- /**
- * Returns an immutable empty set if the argument is null
,
- * or the argument itself otherwise.
- *
- * @param the element type
- * @param set the set, possibly null
- * @return an empty set if the argument is null
- */
- public static Set emptyIfNull(final Set set) {
- return set == null ? Collections.emptySet() : set;
- }
-
- /**
- * Tests two sets for equality as per the equals()
contract
- * in {@link java.util.Set#equals(java.lang.Object)}.
- *
- * This method is useful for implementing Set
when you cannot
- * extend AbstractSet. The method takes Collection instances to enable other
- * collection types to use the Set implementation algorithm.
- *
- * The relevant text (slightly paraphrased as this is a static method) is:
- *
- * Two sets are considered equal if they have
- * the same size, and every member of the first set is contained in
- * the second. This ensures that the {@code equals} method works
- * properly across different implementations of the {@code Set}
- * interface.
- *
- *
- * This implementation first checks if the two sets are the same object:
- * if so it returns {@code true}. Then, it checks if the two sets are
- * identical in size; if not, it returns false. If so, it returns
- * {@code a.containsAll((Collection) b)}.
- *
- *
- * @see java.util.Set
- * @param set1 the first set, may be null
- * @param set2 the second set, may be null
- * @return whether the sets are equal by value comparison
- */
- public static boolean isEqualSet(final Collection> set1, final Collection> set2) {
- if (set1 == set2) {
- return true;
- }
- if (set1 == null || set2 == null || set1.size() != set2.size()) {
- return false;
- }
-
- return set1.containsAll(set2);
- }
-
- /**
- * Generates a hash code using the algorithm specified in
- * {@link java.util.Set#hashCode()}.
- *
- * This method is useful for implementing Set
when you cannot
- * extend AbstractSet. The method takes Collection instances to enable other
- * collection types to use the Set implementation algorithm.
- *
- * @param the element type
- * @see java.util.Set#hashCode()
- * @param set the set to calculate the hash code for, may be null
- * @return the hash code
- */
- public static int hashCodeForSet(final Collection set) {
- if (set == null) {
- return 0;
- }
-
- int hashCode = 0;
- for (final T obj : set) {
- if (obj != null) {
- hashCode += obj.hashCode();
- }
- }
- return hashCode;
- }
-
- /**
- * Returns a new hash set that matches elements based on ==
not
- * equals()
.
- *
- * This set will violate the detail of various Set contracts.
- * As a general rule, don't compare this set to other sets. In particular, you can't
- * use decorators like {@link ListOrderedSet} on it, which silently assume that these
- * contracts are fulfilled.
- *
- * Note that the returned set is not synchronized and is not thread-safe.
- * If you wish to use this set from multiple threads concurrently, you must use
- * appropriate synchronization. The simplest approach is to wrap this map
- * using {@link java.util.Collections#synchronizedSet(Set)}. This class may throw
- * exceptions when accessed by concurrent threads without synchronization.
- *
- * @param the element type
- * @return a new identity hash set
- * @since 4.1
- */
- public static Set newIdentityHashSet() {
- return Collections.newSetFromMap(new IdentityHashMap());
- }
-
- // Set
- //-----------------------------------------------------------------------
- /**
- * Returns a synchronized set backed by the given set.
- *
- * You must manually synchronize on the returned set's iterator to
- * avoid non-deterministic behavior:
- *
- *
- * Set s = SetUtils.synchronizedSet(mySet);
- * synchronized (s) {
- * Iterator i = s.iterator();
- * while (i.hasNext()) {
- * process (i.next());
- * }
- * }
- *
- *
- * This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
- *
- * @param the element type
- * @param set the set to synchronize, must not be null
- * @return a synchronized set backed by the given set
- * @throws NullPointerException if the set is null
- */
- public static Set synchronizedSet(final Set set) {
- return Collections.synchronizedSet(set);
- }
-
- /**
- * Returns an unmodifiable set backed by the given set.
- *
- * This method uses the implementation in the decorators subpackage.
- *
- * @param the element type
- * @param set the set to make unmodifiable, must not be null
- * @return an unmodifiable set backed by the given set
- * @throws NullPointerException if the set is null
- */
- public static Set unmodifiableSet(final Set extends E> set) {
- return UnmodifiableSet.unmodifiableSet(set);
- }
-
- /**
- * Returns a predicated (validating) set backed by the given set.
- *
- * Only objects that pass the test in the given predicate can be added to the set.
- * Trying to add an invalid object results in an IllegalArgumentException.
- * It is important not to use the original set after invoking this method,
- * as it is a backdoor for adding invalid objects.
- *
- * @param the element type
- * @param set the set to predicate, must not be null
- * @param predicate the predicate for the set, must not be null
- * @return a predicated set backed by the given set
- * @throws NullPointerException if the set or predicate is null
- */
- public static Set predicatedSet(final Set set, final Predicate super E> predicate) {
- return PredicatedSet.predicatedSet(set, predicate);
- }
-
- /**
- * Returns a transformed set backed by the given set.
- *
- * Each object is passed through the transformer as it is added to the
- * Set. It is important not to use the original set after invoking this
- * method, as it is a backdoor for adding untransformed objects.
- *
- * Existing entries in the specified set will not be transformed.
- * If you want that behaviour, see {@link TransformedSet#transformedSet}.
- *
- * @param the element type
- * @param set the set to transform, must not be null
- * @param transformer the transformer for the set, must not be null
- * @return a transformed set backed by the given set
- * @throws NullPointerException if the set or transformer is null
- */
- public static Set transformedSet(final Set set,
- final Transformer super E, ? extends E> transformer) {
- return TransformedSet.transformingSet(set, transformer);
- }
-
- /**
- * Returns a set that maintains the order of elements that are added
- * backed by the given set.
- *
- * If an element is added twice, the order is determined by the first add.
- * The order is observed through the iterator or toArray.
- *
- * @param the element type
- * @param set the set to order, must not be null
- * @return an ordered set backed by the given set
- * @throws NullPointerException if the set is null
- */
- public static Set orderedSet(final Set set) {
- return ListOrderedSet.listOrderedSet(set);
- }
-
- // SortedSet
- //-----------------------------------------------------------------------
- /**
- * Returns a synchronized sorted set backed by the given sorted set.
- *
- * You must manually synchronize on the returned set's iterator to
- * avoid non-deterministic behavior:
- *
- *
- * Set s = SetUtils.synchronizedSortedSet(mySet);
- * synchronized (s) {
- * Iterator i = s.iterator();
- * while (i.hasNext()) {
- * process (i.next());
- * }
- * }
- *
- *
- * This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
- *
- * @param the element type
- * @param set the sorted set to synchronize, must not be null
- * @return a synchronized set backed by the given set
- * @throws NullPointerException if the set is null
- */
- public static SortedSet synchronizedSortedSet(final SortedSet set) {
- return Collections.synchronizedSortedSet(set);
- }
-
- /**
- * Returns an unmodifiable sorted set backed by the given sorted set.
- *
- * This method uses the implementation in the decorators subpackage.
- *
- * @param the element type
- * @param set the sorted set to make unmodifiable, must not be null
- * @return an unmodifiable set backed by the given set
- * @throws NullPointerException if the set is null
- */
- public static SortedSet unmodifiableSortedSet(final SortedSet set) {
- return UnmodifiableSortedSet.unmodifiableSortedSet(set);
- }
-
- /**
- * Returns a predicated (validating) sorted set backed by the given sorted set.
- *
- * Only objects that pass the test in the given predicate can be added to the set.
- * Trying to add an invalid object results in an IllegalArgumentException.
- * It is important not to use the original set after invoking this method,
- * as it is a backdoor for adding invalid objects.
- *
- * @param the element type
- * @param set the sorted set to predicate, must not be null
- * @param predicate the predicate for the sorted set, must not be null
- * @return a predicated sorted set backed by the given sorted set
- * @throws NullPointerException if the set or predicate is null
- */
- public static SortedSet predicatedSortedSet(final SortedSet set,
- final Predicate super E> predicate) {
- return PredicatedSortedSet.predicatedSortedSet(set, predicate);
- }
-
- /**
- * Returns a transformed sorted set backed by the given set.
- *
- * Each object is passed through the transformer as it is added to the
- * Set. It is important not to use the original set after invoking this
- * method, as it is a backdoor for adding untransformed objects.
- *
- * Existing entries in the specified set will not be transformed.
- * If you want that behaviour, see {@link TransformedSortedSet#transformedSortedSet}.
- *
- * @param the element type
- * @param set the set to transform, must not be null
- * @param transformer the transformer for the set, must not be null
- * @return a transformed set backed by the given set
- * @throws NullPointerException if the set or transformer is null
- */
- public static SortedSet transformedSortedSet(final SortedSet set,
- final Transformer super E, ? extends E> transformer) {
- return TransformedSortedSet.transformingSortedSet(set, transformer);
- }
-
- // NavigableSet
- //-----------------------------------------------------------------------
- /**
- * Returns an unmodifiable navigable set backed by the given navigable set.
- *
- * This method uses the implementation in the decorators subpackage.
- *
- * @param the element type
- * @param set the navigable set to make unmodifiable, must not be null
- * @return an unmodifiable set backed by the given set
- * @throws NullPointerException if the set is null
- * @since 4.1
- */
- public static SortedSet unmodifiableNavigableSet(final NavigableSet set) {
- return UnmodifiableNavigableSet.unmodifiableNavigableSet(set);
- }
-
- /**
- * Returns a predicated (validating) navigable set backed by the given navigable set.
- *
- * Only objects that pass the test in the given predicate can be added to the set.
- * Trying to add an invalid object results in an IllegalArgumentException.
- * It is important not to use the original set after invoking this method,
- * as it is a backdoor for adding invalid objects.
- *
- * @param the element type
- * @param set the navigable set to predicate, must not be null
- * @param predicate the predicate for the navigable set, must not be null
- * @return a predicated navigable set backed by the given navigable set
- * @throws NullPointerException if the set or predicate is null
- * @since 4.1
- */
- public static SortedSet predicatedNavigableSet(final NavigableSet set,
- final Predicate super E> predicate) {
- return PredicatedNavigableSet.predicatedNavigableSet(set, predicate);
- }
-
- /**
- * Returns a transformed navigable set backed by the given navigable set.
- *
- * Each object is passed through the transformer as it is added to the
- * Set. It is important not to use the original set after invoking this
- * method, as it is a backdoor for adding untransformed objects.
- *
- * Existing entries in the specified set will not be transformed.
- * If you want that behaviour, see {@link TransformedNavigableSet#transformedNavigableSet}.
- *
- * @param the element type
- * @param set the navigable set to transform, must not be null
- * @param transformer the transformer for the set, must not be null
- * @return a transformed set backed by the given set
- * @throws NullPointerException if the set or transformer is null
- * @since 4.1
- */
- public static SortedSet transformedNavigableSet(final NavigableSet set,
- final Transformer super E, ? extends E> transformer) {
- return TransformedNavigableSet.transformingNavigableSet(set, transformer);
- }
-
- // Set operations
- //-----------------------------------------------------------------------
-
- /**
- * Returns a unmodifiable view of the union of the given {@link Set}s.
- *
- * The returned view contains all elements of {@code a} and {@code b}.
- *
- * @param the generic type that is able to represent the types contained
- * in both input sets.
- * @param a the first set, must not be null
- * @param b the second set, must not be null
- * @return a view of the union of the two set
- * @throws NullPointerException if either input set is null
- * @since 4.1
- */
- public static SetView union(final Set extends E> a, final Set extends E> b) {
- if (a == null || b == null) {
- throw new NullPointerException("Sets must not be null.");
- }
-
- final SetView bMinusA = difference(b, a);
-
- return new SetView() {
- @Override
- public boolean contains(final Object o) {
- return a.contains(o) || b.contains(o);
- }
-
- @Override
- public Iterator createIterator() {
- return IteratorUtils.chainedIterator(a.iterator(), bMinusA.iterator());
- }
-
- @Override
- public boolean isEmpty() {
- return a.isEmpty() && b.isEmpty();
- }
-
- @Override
- public int size() {
- return a.size() + bMinusA.size();
- }
- };
- }
-
/**
* Returns a unmodifiable view containing the difference of the given
* {@link Set}s, denoted by {@code a \ b} (or {@code a - b}).
@@ -506,44 +145,6 @@ public class SetUtils {
};
}
- /**
- * Returns a unmodifiable view of the intersection of the given {@link Set}s.
- *
- * The returned view contains all elements that are members of both input sets
- * ({@code a} and {@code b}).
- *
- * @param the generic type that is able to represent the types contained
- * in both input sets.
- * @param a the first set, must not be null
- * @param b the second set, must not be null
- * @return a view of the intersection of the two sets
- * @since 4.1
- */
- public static SetView intersection(final Set extends E> a, final Set extends E> b) {
- if (a == null || b == null) {
- throw new NullPointerException("Sets must not be null.");
- }
-
- final Predicate containedInB = new Predicate() {
- @Override
- public boolean evaluate(final E object) {
- return b.contains(object);
- }
- };
-
- return new SetView() {
- @Override
- public boolean contains(final Object o) {
- return a.contains(o) && b.contains(o);
- }
-
- @Override
- public Iterator createIterator() {
- return IteratorUtils.filteredIterator(a.iterator(), containedInB);
- }
- };
- }
-
/**
* Returns a unmodifiable view of the symmetric difference of the given
* {@link Set}s.
@@ -592,53 +193,452 @@ public class SetUtils {
}
/**
- * An unmodifiable view of a set that may be backed by other sets.
- *
- * If the decorated sets change, this view will change as well. The contents
- * of this view can be transferred to another instance via the {@link #copyInto(Set)}
- * and {@link #toSet()} methods.
+ * Returns an immutable empty set if the argument is null
,
+ * or the argument itself otherwise.
*
+ * @param the element type
+ * @param set the set, possibly null
+ * @return an empty set if the argument is null
+ */
+ public static Set emptyIfNull(final Set set) {
+ return set == null ? Collections.emptySet() : set;
+ }
+
+ //-----------------------------------------------------------------------
+
+ /**
+ * Get a typed empty unmodifiable Set.
* @param the element type
+ * @return an empty Set
+ */
+ public static Set emptySet() {
+ return Collections.emptySet();
+ }
+
+ /**
+ * Get a typed empty unmodifiable sorted set.
+ * @param the element type
+ * @return an empty sorted Set
+ */
+ @SuppressWarnings("unchecked") // empty set is OK for any type
+ public static SortedSet emptySortedSet() {
+ return EMPTY_SORTED_SET;
+ }
+
+ /**
+ * Generates a hash code using the algorithm specified in
+ * {@link java.util.Set#hashCode()}.
+ *
+ * This method is useful for implementing Set
when you cannot
+ * extend AbstractSet. The method takes Collection instances to enable other
+ * collection types to use the Set implementation algorithm.
+ *
+ * @param the element type
+ * @see java.util.Set#hashCode()
+ * @param set the set to calculate the hash code for, may be null
+ * @return the hash code
+ */
+ public static int hashCodeForSet(final Collection set) {
+ if (set == null) {
+ return 0;
+ }
+
+ int hashCode = 0;
+ for (final T obj : set) {
+ if (obj != null) {
+ hashCode += obj.hashCode();
+ }
+ }
+ return hashCode;
+ }
+
+ /**
+ * Returns a unmodifiable view of the intersection of the given {@link Set}s.
+ *
+ * The returned view contains all elements that are members of both input sets
+ * ({@code a} and {@code b}).
+ *
+ * @param the generic type that is able to represent the types contained
+ * in both input sets.
+ * @param a the first set, must not be null
+ * @param b the second set, must not be null
+ * @return a view of the intersection of the two sets
* @since 4.1
*/
- public static abstract class SetView extends AbstractSet {
-
- @Override
- public Iterator iterator() {
- return IteratorUtils.unmodifiableIterator(createIterator());
+ public static SetView intersection(final Set extends E> a, final Set extends E> b) {
+ if (a == null || b == null) {
+ throw new NullPointerException("Sets must not be null.");
}
- /**
- * Return an iterator for this view; the returned iterator is
- * not required to be unmodifiable.
- * @return a new iterator for this view
- */
- protected abstract Iterator createIterator();
+ final Predicate containedInB = new Predicate() {
+ @Override
+ public boolean evaluate(final E object) {
+ return b.contains(object);
+ }
+ };
- @Override
- public int size() {
- return IteratorUtils.size(iterator());
- }
+ return new SetView() {
+ @Override
+ public boolean contains(final Object o) {
+ return a.contains(o) && b.contains(o);
+ }
- /**
- * Copies the contents of this view into the provided set.
- *
- * @param the set type
- * @param set the set for copying the contents
- */
- public > void copyInto(final S set) {
- CollectionUtils.addAll(set, this);
- }
-
- /**
- * Returns a new set containing the contents of this view.
- *
- * @return a new set containing all elements of this view
- */
- public Set toSet() {
- final Set set = new HashSet<>(size());
- copyInto(set);
- return set;
- }
+ @Override
+ public Iterator createIterator() {
+ return IteratorUtils.filteredIterator(a.iterator(), containedInB);
+ }
+ };
}
+
+ /**
+ * Tests two sets for equality as per the equals()
contract
+ * in {@link java.util.Set#equals(java.lang.Object)}.
+ *
+ * This method is useful for implementing Set
when you cannot
+ * extend AbstractSet. The method takes Collection instances to enable other
+ * collection types to use the Set implementation algorithm.
+ *
+ * The relevant text (slightly paraphrased as this is a static method) is:
+ *
+ * Two sets are considered equal if they have
+ * the same size, and every member of the first set is contained in
+ * the second. This ensures that the {@code equals} method works
+ * properly across different implementations of the {@code Set}
+ * interface.
+ *
+ *
+ * This implementation first checks if the two sets are the same object:
+ * if so it returns {@code true}. Then, it checks if the two sets are
+ * identical in size; if not, it returns false. If so, it returns
+ * {@code a.containsAll((Collection) b)}.
+ *
+ *
+ * @see java.util.Set
+ * @param set1 the first set, may be null
+ * @param set2 the second set, may be null
+ * @return whether the sets are equal by value comparison
+ */
+ public static boolean isEqualSet(final Collection> set1, final Collection> set2) {
+ if (set1 == set2) {
+ return true;
+ }
+ if (set1 == null || set2 == null || set1.size() != set2.size()) {
+ return false;
+ }
+
+ return set1.containsAll(set2);
+ }
+
+ /**
+ * Returns a new hash set that matches elements based on ==
not
+ * equals()
.
+ *
+ * This set will violate the detail of various Set contracts.
+ * As a general rule, don't compare this set to other sets. In particular, you can't
+ * use decorators like {@link ListOrderedSet} on it, which silently assume that these
+ * contracts are fulfilled.
+ *
+ * Note that the returned set is not synchronized and is not thread-safe.
+ * If you wish to use this set from multiple threads concurrently, you must use
+ * appropriate synchronization. The simplest approach is to wrap this map
+ * using {@link java.util.Collections#synchronizedSet(Set)}. This class may throw
+ * exceptions when accessed by concurrent threads without synchronization.
+ *
+ * @param the element type
+ * @return a new identity hash set
+ * @since 4.1
+ */
+ public static Set newIdentityHashSet() {
+ return Collections.newSetFromMap(new IdentityHashMap());
+ }
+
+ /**
+ * Returns a set that maintains the order of elements that are added
+ * backed by the given set.
+ *
+ * If an element is added twice, the order is determined by the first add.
+ * The order is observed through the iterator or toArray.
+ *
+ * @param the element type
+ * @param set the set to order, must not be null
+ * @return an ordered set backed by the given set
+ * @throws NullPointerException if the set is null
+ */
+ public static Set orderedSet(final Set set) {
+ return ListOrderedSet.listOrderedSet(set);
+ }
+
+ /**
+ * Returns a predicated (validating) navigable set backed by the given navigable set.
+ *
+ * Only objects that pass the test in the given predicate can be added to the set.
+ * Trying to add an invalid object results in an IllegalArgumentException.
+ * It is important not to use the original set after invoking this method,
+ * as it is a backdoor for adding invalid objects.
+ *
+ * @param the element type
+ * @param set the navigable set to predicate, must not be null
+ * @param predicate the predicate for the navigable set, must not be null
+ * @return a predicated navigable set backed by the given navigable set
+ * @throws NullPointerException if the set or predicate is null
+ * @since 4.1
+ */
+ public static SortedSet predicatedNavigableSet(final NavigableSet set,
+ final Predicate super E> predicate) {
+ return PredicatedNavigableSet.predicatedNavigableSet(set, predicate);
+ }
+
+ /**
+ * Returns a predicated (validating) set backed by the given set.
+ *
+ * Only objects that pass the test in the given predicate can be added to the set.
+ * Trying to add an invalid object results in an IllegalArgumentException.
+ * It is important not to use the original set after invoking this method,
+ * as it is a backdoor for adding invalid objects.
+ *
+ * @param the element type
+ * @param set the set to predicate, must not be null
+ * @param predicate the predicate for the set, must not be null
+ * @return a predicated set backed by the given set
+ * @throws NullPointerException if the set or predicate is null
+ */
+ public static Set predicatedSet(final Set set, final Predicate super E> predicate) {
+ return PredicatedSet.predicatedSet(set, predicate);
+ }
+
+ /**
+ * Returns a predicated (validating) sorted set backed by the given sorted set.
+ *
+ * Only objects that pass the test in the given predicate can be added to the set.
+ * Trying to add an invalid object results in an IllegalArgumentException.
+ * It is important not to use the original set after invoking this method,
+ * as it is a backdoor for adding invalid objects.
+ *
+ * @param the element type
+ * @param set the sorted set to predicate, must not be null
+ * @param predicate the predicate for the sorted set, must not be null
+ * @return a predicated sorted set backed by the given sorted set
+ * @throws NullPointerException if the set or predicate is null
+ */
+ public static SortedSet predicatedSortedSet(final SortedSet set,
+ final Predicate super E> predicate) {
+ return PredicatedSortedSet.predicatedSortedSet(set, predicate);
+ }
+
+ // Set
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a synchronized set backed by the given set.
+ *
+ * You must manually synchronize on the returned set's iterator to
+ * avoid non-deterministic behavior:
+ *
+ *
+ * Set s = SetUtils.synchronizedSet(mySet);
+ * synchronized (s) {
+ * Iterator i = s.iterator();
+ * while (i.hasNext()) {
+ * process (i.next());
+ * }
+ * }
+ *
+ *
+ * This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
+ *
+ * @param the element type
+ * @param set the set to synchronize, must not be null
+ * @return a synchronized set backed by the given set
+ * @throws NullPointerException if the set is null
+ */
+ public static Set synchronizedSet(final Set set) {
+ return Collections.synchronizedSet(set);
+ }
+
+ // SortedSet
+ //-----------------------------------------------------------------------
+ /**
+ * Returns a synchronized sorted set backed by the given sorted set.
+ *
+ * You must manually synchronize on the returned set's iterator to
+ * avoid non-deterministic behavior:
+ *
+ *
+ * Set s = SetUtils.synchronizedSortedSet(mySet);
+ * synchronized (s) {
+ * Iterator i = s.iterator();
+ * while (i.hasNext()) {
+ * process (i.next());
+ * }
+ * }
+ *
+ *
+ * This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
+ *
+ * @param the element type
+ * @param set the sorted set to synchronize, must not be null
+ * @return a synchronized set backed by the given set
+ * @throws NullPointerException if the set is null
+ */
+ public static SortedSet synchronizedSortedSet(final SortedSet set) {
+ return Collections.synchronizedSortedSet(set);
+ }
+
+ /**
+ * Returns a transformed navigable set backed by the given navigable set.
+ *
+ * Each object is passed through the transformer as it is added to the
+ * Set. It is important not to use the original set after invoking this
+ * method, as it is a backdoor for adding untransformed objects.
+ *
+ * Existing entries in the specified set will not be transformed.
+ * If you want that behaviour, see {@link TransformedNavigableSet#transformedNavigableSet}.
+ *
+ * @param the element type
+ * @param set the navigable set to transform, must not be null
+ * @param transformer the transformer for the set, must not be null
+ * @return a transformed set backed by the given set
+ * @throws NullPointerException if the set or transformer is null
+ * @since 4.1
+ */
+ public static SortedSet transformedNavigableSet(final NavigableSet set,
+ final Transformer super E, ? extends E> transformer) {
+ return TransformedNavigableSet.transformingNavigableSet(set, transformer);
+ }
+
+ /**
+ * Returns a transformed set backed by the given set.
+ *
+ * Each object is passed through the transformer as it is added to the
+ * Set. It is important not to use the original set after invoking this
+ * method, as it is a backdoor for adding untransformed objects.
+ *
+ * Existing entries in the specified set will not be transformed.
+ * If you want that behaviour, see {@link TransformedSet#transformedSet}.
+ *
+ * @param the element type
+ * @param set the set to transform, must not be null
+ * @param transformer the transformer for the set, must not be null
+ * @return a transformed set backed by the given set
+ * @throws NullPointerException if the set or transformer is null
+ */
+ public static Set transformedSet(final Set set,
+ final Transformer super E, ? extends E> transformer) {
+ return TransformedSet.transformingSet(set, transformer);
+ }
+
+ /**
+ * Returns a transformed sorted set backed by the given set.
+ *
+ * Each object is passed through the transformer as it is added to the
+ * Set. It is important not to use the original set after invoking this
+ * method, as it is a backdoor for adding untransformed objects.
+ *
+ * Existing entries in the specified set will not be transformed.
+ * If you want that behaviour, see {@link TransformedSortedSet#transformedSortedSet}.
+ *
+ * @param the element type
+ * @param set the set to transform, must not be null
+ * @param transformer the transformer for the set, must not be null
+ * @return a transformed set backed by the given set
+ * @throws NullPointerException if the set or transformer is null
+ */
+ public static SortedSet transformedSortedSet(final SortedSet set,
+ final Transformer super E, ? extends E> transformer) {
+ return TransformedSortedSet.transformingSortedSet(set, transformer);
+ }
+
+ /**
+ * Returns a unmodifiable view of the union of the given {@link Set}s.
+ *
+ * The returned view contains all elements of {@code a} and {@code b}.
+ *
+ * @param the generic type that is able to represent the types contained
+ * in both input sets.
+ * @param a the first set, must not be null
+ * @param b the second set, must not be null
+ * @return a view of the union of the two set
+ * @throws NullPointerException if either input set is null
+ * @since 4.1
+ */
+ public static SetView union(final Set extends E> a, final Set extends E> b) {
+ if (a == null || b == null) {
+ throw new NullPointerException("Sets must not be null.");
+ }
+
+ final SetView bMinusA = difference(b, a);
+
+ return new SetView() {
+ @Override
+ public boolean contains(final Object o) {
+ return a.contains(o) || b.contains(o);
+ }
+
+ @Override
+ public Iterator createIterator() {
+ return IteratorUtils.chainedIterator(a.iterator(), bMinusA.iterator());
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return a.isEmpty() && b.isEmpty();
+ }
+
+ @Override
+ public int size() {
+ return a.size() + bMinusA.size();
+ }
+ };
+ }
+
+ // Set operations
+ //-----------------------------------------------------------------------
+
+ // NavigableSet
+ //-----------------------------------------------------------------------
+ /**
+ * Returns an unmodifiable navigable set backed by the given navigable set.
+ *
+ * This method uses the implementation in the decorators subpackage.
+ *
+ * @param the element type
+ * @param set the navigable set to make unmodifiable, must not be null
+ * @return an unmodifiable set backed by the given set
+ * @throws NullPointerException if the set is null
+ * @since 4.1
+ */
+ public static SortedSet unmodifiableNavigableSet(final NavigableSet set) {
+ return UnmodifiableNavigableSet.unmodifiableNavigableSet(set);
+ }
+
+ /**
+ * Returns an unmodifiable set backed by the given set.
+ *
+ * This method uses the implementation in the decorators subpackage.
+ *
+ * @param the element type
+ * @param set the set to make unmodifiable, must not be null
+ * @return an unmodifiable set backed by the given set
+ * @throws NullPointerException if the set is null
+ */
+ public static Set unmodifiableSet(final Set extends E> set) {
+ return UnmodifiableSet.unmodifiableSet(set);
+ }
+
+ /**
+ * Create an unmodifiable set from the given items. If the passed var-args argument is {@code
+ * null}, then the method returns {@code null}.
+ * @param the element type
+ * @return a set
+ */
+ public static Set unmodifiableSetSet(final E... items) {
+ if (items == null) {
+ return null;
+ }
+ return Collections.unmodifiableSet(new HashSet<>(Arrays.asList(items)));
+ }
+
+ /**
+ * SetUtils
should not normally be instantiated.
+ */
+ private SetUtils() {}
}