001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4;
018
019import java.util.AbstractSet;
020import java.util.Collection;
021import java.util.Collections;
022import java.util.HashSet;
023import java.util.IdentityHashMap;
024import java.util.Iterator;
025import java.util.NavigableSet;
026import java.util.Set;
027import java.util.SortedSet;
028import java.util.TreeSet;
029
030import org.apache.commons.collections4.set.ListOrderedSet;
031import org.apache.commons.collections4.set.PredicatedNavigableSet;
032import org.apache.commons.collections4.set.PredicatedSet;
033import org.apache.commons.collections4.set.PredicatedSortedSet;
034import org.apache.commons.collections4.set.TransformedNavigableSet;
035import org.apache.commons.collections4.set.TransformedSet;
036import org.apache.commons.collections4.set.TransformedSortedSet;
037import org.apache.commons.collections4.set.UnmodifiableNavigableSet;
038import org.apache.commons.collections4.set.UnmodifiableSet;
039import org.apache.commons.collections4.set.UnmodifiableSortedSet;
040
041/**
042 * Provides utility methods and decorators for
043 * {@link Set} and {@link SortedSet} instances.
044 *
045 * @since 2.1
046 */
047public class SetUtils {
048
049    /**
050     * Get a typed empty unmodifiable Set.
051     * @param <E> the element type
052     * @return an empty Set
053     */
054    public static <E> Set<E> emptySet() {
055        return Collections.<E>emptySet();
056    }
057
058    /**
059     * An empty unmodifiable sorted set.
060     * This is not provided in the JDK.
061     */
062    @SuppressWarnings("rawtypes")
063    public static final SortedSet EMPTY_SORTED_SET =
064            UnmodifiableSortedSet.unmodifiableSortedSet(new TreeSet<>());
065
066    /**
067     * Get a typed empty unmodifiable sorted set.
068     * @param <E> the element type
069     * @return an empty sorted Set
070     */
071    @SuppressWarnings("unchecked") // empty set is OK for any type
072    public static <E> SortedSet<E> emptySortedSet() {
073        return EMPTY_SORTED_SET;
074    }
075
076    /**
077     * <code>SetUtils</code> should not normally be instantiated.
078     */
079    private SetUtils() {}
080
081    //-----------------------------------------------------------------------
082
083    /**
084     * Returns an immutable empty set if the argument is <code>null</code>,
085     * or the argument itself otherwise.
086     *
087     * @param <T> the element type
088     * @param set the set, possibly <code>null</code>
089     * @return an empty set if the argument is <code>null</code>
090     */
091    public static <T> Set<T> emptyIfNull(final Set<T> set) {
092        return set == null ? Collections.<T>emptySet() : set;
093    }
094
095    /**
096     * Tests two sets for equality as per the <code>equals()</code> contract
097     * in {@link java.util.Set#equals(java.lang.Object)}.
098     * <p>
099     * This method is useful for implementing <code>Set</code> when you cannot
100     * extend AbstractSet. The method takes Collection instances to enable other
101     * collection types to use the Set implementation algorithm.
102     * <p>
103     * The relevant text (slightly paraphrased as this is a static method) is:
104     * <blockquote>
105     * <p>Two sets are considered equal if they have
106     * the same size, and every member of the first set is contained in
107     * the second. This ensures that the {@code equals} method works
108     * properly across different implementations of the {@code Set}
109     * interface.</p>
110     *
111     * <p>
112     * This implementation first checks if the two sets are the same object:
113     * if so it returns {@code true}.  Then, it checks if the two sets are
114     * identical in size; if not, it returns false. If so, it returns
115     * {@code a.containsAll((Collection) b)}.</p>
116     * </blockquote>
117     *
118     * @see java.util.Set
119     * @param set1  the first set, may be null
120     * @param set2  the second set, may be null
121     * @return whether the sets are equal by value comparison
122     */
123    public static boolean isEqualSet(final Collection<?> set1, final Collection<?> set2) {
124        if (set1 == set2) {
125            return true;
126        }
127        if (set1 == null || set2 == null || set1.size() != set2.size()) {
128            return false;
129        }
130
131        return set1.containsAll(set2);
132    }
133
134    /**
135     * Generates a hash code using the algorithm specified in
136     * {@link java.util.Set#hashCode()}.
137     * <p>
138     * This method is useful for implementing <code>Set</code> when you cannot
139     * extend AbstractSet. The method takes Collection instances to enable other
140     * collection types to use the Set implementation algorithm.
141     *
142     * @param <T> the element type
143     * @see java.util.Set#hashCode()
144     * @param set  the set to calculate the hash code for, may be null
145     * @return the hash code
146     */
147    public static <T> int hashCodeForSet(final Collection<T> set) {
148        if (set == null) {
149            return 0;
150        }
151
152        int hashCode = 0;
153        for (final T obj : set) {
154            if (obj != null) {
155                hashCode += obj.hashCode();
156            }
157        }
158        return hashCode;
159    }
160
161    /**
162     * Returns a new hash set that matches elements based on <code>==</code> not
163     * <code>equals()</code>.
164     * <p>
165     * <strong>This set will violate the detail of various Set contracts.</strong>
166     * As a general rule, don't compare this set to other sets. In particular, you can't
167     * use decorators like {@link ListOrderedSet} on it, which silently assume that these
168     * contracts are fulfilled.
169     * <p>
170     * <strong>Note that the returned set is not synchronized and is not thread-safe.</strong>
171     * If you wish to use this set from multiple threads concurrently, you must use
172     * appropriate synchronization. The simplest approach is to wrap this map
173     * using {@link java.util.Collections#synchronizedSet(Set)}. This class may throw
174     * exceptions when accessed by concurrent threads without synchronization.
175     *
176     * @param <E>  the element type
177     * @return a new identity hash set
178     * @since 4.1
179     */
180    public static <E> Set<E> newIdentityHashSet() {
181        return Collections.newSetFromMap(new IdentityHashMap<E, Boolean>());
182    }
183
184    // Set
185    //-----------------------------------------------------------------------
186    /**
187     * Returns a synchronized set backed by the given set.
188     * <p>
189     * You must manually synchronize on the returned set's iterator to
190     * avoid non-deterministic behavior:
191     *
192     * <pre>
193     * Set s = SetUtils.synchronizedSet(mySet);
194     * synchronized (s) {
195     *     Iterator i = s.iterator();
196     *     while (i.hasNext()) {
197     *         process (i.next());
198     *     }
199     * }
200     * </pre>
201     *
202     * This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
203     *
204     * @param <E> the element type
205     * @param set  the set to synchronize, must not be null
206     * @return a synchronized set backed by the given set
207     * @throws NullPointerException if the set is null
208     */
209    public static <E> Set<E> synchronizedSet(final Set<E> set) {
210        return Collections.synchronizedSet(set);
211    }
212
213    /**
214     * Returns an unmodifiable set backed by the given set.
215     * <p>
216     * This method uses the implementation in the decorators subpackage.
217     *
218     * @param <E> the element type
219     * @param set  the set to make unmodifiable, must not be null
220     * @return an unmodifiable set backed by the given set
221     * @throws NullPointerException if the set is null
222     */
223    public static <E> Set<E> unmodifiableSet(final Set<? extends E> set) {
224        return UnmodifiableSet.unmodifiableSet(set);
225    }
226
227    /**
228     * Returns a predicated (validating) set backed by the given set.
229     * <p>
230     * Only objects that pass the test in the given predicate can be added to the set.
231     * Trying to add an invalid object results in an IllegalArgumentException.
232     * It is important not to use the original set after invoking this method,
233     * as it is a backdoor for adding invalid objects.
234     *
235     * @param <E> the element type
236     * @param set  the set to predicate, must not be null
237     * @param predicate  the predicate for the set, must not be null
238     * @return a predicated set backed by the given set
239     * @throws NullPointerException if the set or predicate is null
240     */
241    public static <E> Set<E> predicatedSet(final Set<E> set, final Predicate<? super E> predicate) {
242        return PredicatedSet.predicatedSet(set, predicate);
243    }
244
245    /**
246     * Returns a transformed set backed by the given set.
247     * <p>
248     * Each object is passed through the transformer as it is added to the
249     * Set. It is important not to use the original set after invoking this
250     * method, as it is a backdoor for adding untransformed objects.
251     * <p>
252     * Existing entries in the specified set will not be transformed.
253     * If you want that behaviour, see {@link TransformedSet#transformedSet}.
254     *
255     * @param <E> the element type
256     * @param set  the set to transform, must not be null
257     * @param transformer  the transformer for the set, must not be null
258     * @return a transformed set backed by the given set
259     * @throws NullPointerException if the set or transformer is null
260     */
261    public static <E> Set<E> transformedSet(final Set<E> set,
262                                            final Transformer<? super E, ? extends E> transformer) {
263        return TransformedSet.transformingSet(set, transformer);
264    }
265
266    /**
267     * Returns a set that maintains the order of elements that are added
268     * backed by the given set.
269     * <p>
270     * If an element is added twice, the order is determined by the first add.
271     * The order is observed through the iterator or toArray.
272     *
273     * @param <E> the element type
274     * @param set  the set to order, must not be null
275     * @return an ordered set backed by the given set
276     * @throws NullPointerException if the set is null
277     */
278    public static <E> Set<E> orderedSet(final Set<E> set) {
279        return ListOrderedSet.listOrderedSet(set);
280    }
281
282    // SortedSet
283    //-----------------------------------------------------------------------
284    /**
285     * Returns a synchronized sorted set backed by the given sorted set.
286     * <p>
287     * You must manually synchronize on the returned set's iterator to
288     * avoid non-deterministic behavior:
289     *
290     * <pre>
291     * Set s = SetUtils.synchronizedSortedSet(mySet);
292     * synchronized (s) {
293     *     Iterator i = s.iterator();
294     *     while (i.hasNext()) {
295     *         process (i.next());
296     *     }
297     * }
298     * </pre>
299     *
300     * This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
301     *
302     * @param <E> the element type
303     * @param set  the sorted set to synchronize, must not be null
304     * @return a synchronized set backed by the given set
305     * @throws NullPointerException if the set is null
306     */
307    public static <E> SortedSet<E> synchronizedSortedSet(final SortedSet<E> set) {
308        return Collections.synchronizedSortedSet(set);
309    }
310
311    /**
312     * Returns an unmodifiable sorted set backed by the given sorted set.
313     * <p>
314     * This method uses the implementation in the decorators subpackage.
315     *
316     * @param <E> the element type
317     * @param set  the sorted set to make unmodifiable, must not be null
318     * @return an unmodifiable set backed by the given set
319     * @throws NullPointerException if the set is null
320     */
321    public static <E> SortedSet<E> unmodifiableSortedSet(final SortedSet<E> set) {
322        return UnmodifiableSortedSet.unmodifiableSortedSet(set);
323    }
324
325    /**
326     * Returns a predicated (validating) sorted set backed by the given sorted set.
327     * <p>
328     * Only objects that pass the test in the given predicate can be added to the set.
329     * Trying to add an invalid object results in an IllegalArgumentException.
330     * It is important not to use the original set after invoking this method,
331     * as it is a backdoor for adding invalid objects.
332     *
333     * @param <E> the element type
334     * @param set  the sorted set to predicate, must not be null
335     * @param predicate  the predicate for the sorted set, must not be null
336     * @return a predicated sorted set backed by the given sorted set
337     * @throws NullPointerException if the set or predicate is null
338     */
339    public static <E> SortedSet<E> predicatedSortedSet(final SortedSet<E> set,
340                                                       final Predicate<? super E> predicate) {
341        return PredicatedSortedSet.predicatedSortedSet(set, predicate);
342    }
343
344    /**
345     * Returns a transformed sorted set backed by the given set.
346     * <p>
347     * Each object is passed through the transformer as it is added to the
348     * Set. It is important not to use the original set after invoking this
349     * method, as it is a backdoor for adding untransformed objects.
350     * <p>
351     * Existing entries in the specified set will not be transformed.
352     * If you want that behaviour, see {@link TransformedSortedSet#transformedSortedSet}.
353     *
354     * @param <E> the element type
355     * @param set  the set to transform, must not be null
356     * @param transformer  the transformer for the set, must not be null
357     * @return a transformed set backed by the given set
358     * @throws NullPointerException if the set or transformer is null
359     */
360    public static <E> SortedSet<E> transformedSortedSet(final SortedSet<E> set,
361                                                        final Transformer<? super E, ? extends E> transformer) {
362        return TransformedSortedSet.transformingSortedSet(set, transformer);
363    }
364
365    // NavigableSet
366    //-----------------------------------------------------------------------
367    /**
368     * Returns an unmodifiable navigable set backed by the given navigable set.
369     * <p>
370     * This method uses the implementation in the decorators subpackage.
371     *
372     * @param <E> the element type
373     * @param set  the navigable set to make unmodifiable, must not be null
374     * @return an unmodifiable set backed by the given set
375     * @throws NullPointerException if the set is null
376     * @since 4.1
377     */
378    public static <E> SortedSet<E> unmodifiableNavigableSet(final NavigableSet<E> set) {
379        return UnmodifiableNavigableSet.unmodifiableNavigableSet(set);
380    }
381
382    /**
383     * Returns a predicated (validating) navigable set backed by the given navigable set.
384     * <p>
385     * Only objects that pass the test in the given predicate can be added to the set.
386     * Trying to add an invalid object results in an IllegalArgumentException.
387     * It is important not to use the original set after invoking this method,
388     * as it is a backdoor for adding invalid objects.
389     *
390     * @param <E> the element type
391     * @param set  the navigable set to predicate, must not be null
392     * @param predicate  the predicate for the navigable set, must not be null
393     * @return a predicated navigable set backed by the given navigable set
394     * @throws NullPointerException if the set or predicate is null
395     * @since 4.1
396     */
397    public static <E> SortedSet<E> predicatedNavigableSet(final NavigableSet<E> set,
398                                                          final Predicate<? super E> predicate) {
399        return PredicatedNavigableSet.predicatedNavigableSet(set, predicate);
400    }
401
402    /**
403     * Returns a transformed navigable set backed by the given navigable set.
404     * <p>
405     * Each object is passed through the transformer as it is added to the
406     * Set. It is important not to use the original set after invoking this
407     * method, as it is a backdoor for adding untransformed objects.
408     * <p>
409     * Existing entries in the specified set will not be transformed.
410     * If you want that behaviour, see {@link TransformedNavigableSet#transformedNavigableSet}.
411     *
412     * @param <E> the element type
413     * @param set  the navigable set to transform, must not be null
414     * @param transformer  the transformer for the set, must not be null
415     * @return a transformed set backed by the given set
416     * @throws NullPointerException if the set or transformer is null
417     * @since 4.1
418     */
419    public static <E> SortedSet<E> transformedNavigableSet(final NavigableSet<E> set,
420                                                           final Transformer<? super E, ? extends E> transformer) {
421        return TransformedNavigableSet.transformingNavigableSet(set, transformer);
422    }
423
424    // Set operations
425    //-----------------------------------------------------------------------
426
427    /**
428     * Returns a unmodifiable <b>view</b> of the union of the given {@link Set}s.
429     * <p>
430     * The returned view contains all elements of {@code a} and {@code b}.
431     *
432     * @param <E> the generic type that is able to represent the types contained
433     *   in both input sets.
434     * @param a  the first set, must not be null
435     * @param b  the second set, must not be null
436     * @return a view of the union of the two set
437     * @throws NullPointerException if either input set is null
438     * @since 4.1
439     */
440    public static <E> SetView<E> union(final Set<? extends E> a, final Set<? extends E> b) {
441        if (a == null || b == null) {
442            throw new NullPointerException("Sets must not be null.");
443        }
444
445        final SetView<E> bMinusA = difference(b, a);
446
447        return new SetView<E>() {
448            @Override
449            public boolean contains(final Object o) {
450                return a.contains(o) || b.contains(o);
451            }
452
453            @Override
454            public Iterator<E> createIterator() {
455                return IteratorUtils.chainedIterator(a.iterator(), bMinusA.iterator());
456            }
457
458            @Override
459            public boolean isEmpty() {
460                return a.isEmpty() && b.isEmpty();
461            }
462
463            @Override
464            public int size() {
465                return a.size() + bMinusA.size();
466            }
467        };
468    }
469
470    /**
471     * Returns a unmodifiable <b>view</b> containing the difference of the given
472     * {@link Set}s, denoted by {@code a \ b} (or {@code a - b}).
473     * <p>
474     * The returned view contains all elements of {@code a} that are not a member
475     * of {@code b}.
476     *
477     * @param <E> the generic type that is able to represent the types contained
478     *   in both input sets.
479     * @param a  the set to subtract from, must not be null
480     * @param b  the set to subtract, must not be null
481     * @return a view of the relative complement of  of the two sets
482     * @since 4.1
483     */
484    public static <E> SetView<E> difference(final Set<? extends E> a, final Set<? extends E> b) {
485        if (a == null || b == null) {
486            throw new NullPointerException("Sets must not be null.");
487        }
488
489        final Predicate<E> notContainedInB = new Predicate<E>() {
490            @Override
491            public boolean evaluate(final E object) {
492                return !b.contains(object);
493            }
494        };
495
496        return new SetView<E>() {
497            @Override
498            public boolean contains(final Object o) {
499                return a.contains(o) && !b.contains(o);
500            }
501
502            @Override
503            public Iterator<E> createIterator() {
504                return IteratorUtils.filteredIterator(a.iterator(), notContainedInB);
505            }
506        };
507    }
508
509    /**
510     * Returns a unmodifiable <b>view</b> of the intersection of the given {@link Set}s.
511     * <p>
512     * The returned view contains all elements that are members of both input sets
513     * ({@code a} and {@code b}).
514     *
515     * @param <E> the generic type that is able to represent the types contained
516     *   in both input sets.
517     * @param a  the first set, must not be null
518     * @param b  the second set, must not be null
519     * @return a view of the intersection of the two sets
520     * @since 4.1
521     */
522    public static <E> SetView<E> intersection(final Set<? extends E> a, final Set<? extends E> b) {
523        if (a == null || b == null) {
524            throw new NullPointerException("Sets must not be null.");
525        }
526
527        final Predicate<E> containedInB = new Predicate<E>() {
528            @Override
529            public boolean evaluate(final E object) {
530                return b.contains(object);
531            }
532        };
533
534        return new SetView<E>() {
535            @Override
536            public boolean contains(final Object o) {
537                return a.contains(o) && b.contains(o);
538            }
539
540            @Override
541            public Iterator<E> createIterator() {
542                return IteratorUtils.filteredIterator(a.iterator(), containedInB);
543            }
544        };
545    }
546
547    /**
548     * Returns a unmodifiable <b>view</b> of the symmetric difference of the given
549     * {@link Set}s.
550     * <p>
551     * The returned view contains all elements of {@code a} and {@code b} that are
552     * not a member of the other set.
553     * <p>
554     * This is equivalent to {@code union(difference(a, b), difference(b, a))}.
555     *
556     * @param <E> the generic type that is able to represent the types contained
557     *   in both input sets.
558     * @param a  the first set, must not be null
559     * @param b  the second set, must not be null
560     * @return a view of the symmetric difference of the two sets
561     * @since 4.1
562     */
563    public static <E> SetView<E> disjunction(final Set<? extends E> a, final Set<? extends E> b) {
564        if (a == null || b == null) {
565            throw new NullPointerException("Sets must not be null.");
566        }
567
568        final SetView<E> aMinusB = difference(a, b);
569        final SetView<E> bMinusA = difference(b, a);
570
571        return new SetView<E>() {
572            @Override
573            public boolean contains(final Object o) {
574                return a.contains(o) ^ b.contains(o);
575            }
576
577            @Override
578            public Iterator<E> createIterator() {
579                return IteratorUtils.chainedIterator(aMinusB.iterator(), bMinusA.iterator());
580            }
581
582            @Override
583            public boolean isEmpty() {
584                return aMinusB.isEmpty() && bMinusA.isEmpty();
585            }
586
587            @Override
588            public int size() {
589                return aMinusB.size() + bMinusA.size();
590            }
591        };
592    }
593
594    /**
595     * An unmodifiable <b>view</b> of a set that may be backed by other sets.
596     * <p>
597     * If the decorated sets change, this view will change as well. The contents
598     * of this view can be transferred to another instance via the {@link #copyInto(Set)}
599     * and {@link #toSet()} methods.
600     *
601     * @param <E> the element type
602     * @since 4.1
603     */
604    public static abstract class SetView<E> extends AbstractSet<E> {
605
606        @Override
607        public Iterator<E> iterator() {
608            return IteratorUtils.unmodifiableIterator(createIterator());
609        }
610
611        /**
612         * Return an iterator for this view; the returned iterator is
613         * not required to be unmodifiable.
614         * @return a new iterator for this view
615         */
616        protected abstract Iterator<E> createIterator();
617
618        @Override
619        public int size() {
620            return IteratorUtils.size(iterator());
621        }
622
623        /**
624         * Copies the contents of this view into the provided set.
625         *
626         * @param <S> the set type
627         * @param set  the set for copying the contents
628         */
629        public <S extends Set<E>> void copyInto(final S set) {
630            CollectionUtils.addAll(set, this);
631        }
632
633        /**
634         * Returns a new set containing the contents of this view.
635         *
636         * @return a new set containing all elements of this view
637         */
638        public Set<E> toSet() {
639            final Set<E> set = new HashSet<>(size());
640            copyInto(set);
641            return set;
642        }
643    }
644}