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.Collection;
020import java.util.Collections;
021import java.util.Set;
022import java.util.SortedSet;
023import java.util.TreeSet;
024
025import org.apache.commons.collections4.set.ListOrderedSet;
026import org.apache.commons.collections4.set.PredicatedSet;
027import org.apache.commons.collections4.set.PredicatedSortedSet;
028import org.apache.commons.collections4.set.TransformedSet;
029import org.apache.commons.collections4.set.TransformedSortedSet;
030import org.apache.commons.collections4.set.UnmodifiableSet;
031import org.apache.commons.collections4.set.UnmodifiableSortedSet;
032
033/**
034 * Provides utility methods and decorators for
035 * {@link Set} and {@link SortedSet} instances.
036 *
037 * @since 2.1
038 * @version $Id: SetUtils.html 972421 2015-11-14 20:00:04Z tn $
039 */
040public class SetUtils {
041
042    /**
043     * Get a typed empty unmodifiable Set.
044     * @param <E> the element type
045     * @return an empty Set
046     */
047    public static <E> Set<E> emptySet() {
048        return Collections.<E>emptySet();
049    }
050
051    /**
052     * An empty unmodifiable sorted set.
053     * This is not provided in the JDK.
054     */
055    @SuppressWarnings("rawtypes")
056    public static final SortedSet EMPTY_SORTED_SET =
057            UnmodifiableSortedSet.unmodifiableSortedSet(new TreeSet<Object>());
058
059    /**
060     * Get a typed empty unmodifiable sorted set.
061     * @param <E> the element type
062     * @return an empty sorted Set
063     */
064    @SuppressWarnings("unchecked") // empty set is OK for any type
065    public static <E> SortedSet<E> emptySortedSet() {
066        return (SortedSet<E>) EMPTY_SORTED_SET;
067    }
068
069    /**
070     * <code>SetUtils</code> should not normally be instantiated.
071     */
072    private SetUtils() {}
073
074    //-----------------------------------------------------------------------
075
076    /**
077     * Returns an immutable empty set if the argument is <code>null</code>,
078     * or the argument itself otherwise.
079     *
080     * @param <T> the element type
081     * @param set the set, possibly <code>null</code>
082     * @return an empty set if the argument is <code>null</code>
083     */
084    public static <T> Set<T> emptyIfNull(final Set<T> set) {
085        return set == null ? Collections.<T>emptySet() : set;
086    }
087
088    /**
089     * Tests two sets for equality as per the <code>equals()</code> contract
090     * in {@link java.util.Set#equals(java.lang.Object)}.
091     * <p>
092     * This method is useful for implementing <code>Set</code> when you cannot
093     * extend AbstractSet. The method takes Collection instances to enable other
094     * collection types to use the Set implementation algorithm.
095     * <p>
096     * The relevant text (slightly paraphrased as this is a static method) is:
097     * <blockquote>
098     * <p>Two sets are considered equal if they have
099     * the same size, and every member of the first set is contained in
100     * the second. This ensures that the <tt>equals</tt> method works
101     * properly across different implementations of the <tt>Set</tt>
102     * interface.</p>
103     *
104     * <p>
105     * This implementation first checks if the two sets are the same object:
106     * if so it returns <tt>true</tt>.  Then, it checks if the two sets are
107     * identical in size; if not, it returns false. If so, it returns
108     * <tt>a.containsAll((Collection) b)</tt>.</p>
109     * </blockquote>
110     *
111     * @see java.util.Set
112     * @param set1  the first set, may be null
113     * @param set2  the second set, may be null
114     * @return whether the sets are equal by value comparison
115     */
116    public static boolean isEqualSet(final Collection<?> set1, final Collection<?> set2) {
117        if (set1 == set2) {
118            return true;
119        }
120        if (set1 == null || set2 == null || set1.size() != set2.size()) {
121            return false;
122        }
123
124        return set1.containsAll(set2);
125    }
126
127    /**
128     * Generates a hash code using the algorithm specified in
129     * {@link java.util.Set#hashCode()}.
130     * <p>
131     * This method is useful for implementing <code>Set</code> when you cannot
132     * extend AbstractSet. The method takes Collection instances to enable other
133     * collection types to use the Set implementation algorithm.
134     *
135     * @param <T> the element type
136     * @see java.util.Set#hashCode()
137     * @param set  the set to calculate the hash code for, may be null
138     * @return the hash code
139     */
140    public static <T> int hashCodeForSet(final Collection<T> set) {
141        if (set == null) {
142            return 0;
143        }
144
145        int hashCode = 0;
146        for (final T obj : set) {
147            if (obj != null) {
148                hashCode += obj.hashCode();
149            }
150        }
151        return hashCode;
152    }
153
154    //-----------------------------------------------------------------------
155    /**
156     * Returns a synchronized set backed by the given set.
157     * <p>
158     * You must manually synchronize on the returned set's iterator to
159     * avoid non-deterministic behavior:
160     *
161     * <pre>
162     * Set s = SetUtils.synchronizedSet(mySet);
163     * synchronized (s) {
164     *     Iterator i = s.iterator();
165     *     while (i.hasNext()) {
166     *         process (i.next());
167     *     }
168     * }
169     * </pre>
170     *
171     * This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
172     *
173     * @param <E> the element type
174     * @param set  the set to synchronize, must not be null
175     * @return a synchronized set backed by the given set
176     * @throws IllegalArgumentException  if the set is null
177     */
178    public static <E> Set<E> synchronizedSet(final Set<E> set) {
179        return Collections.synchronizedSet(set);
180    }
181
182    /**
183     * Returns an unmodifiable set backed by the given set.
184     * <p>
185     * This method uses the implementation in the decorators subpackage.
186     *
187     * @param <E> the element type
188     * @param set  the set to make unmodifiable, must not be null
189     * @return an unmodifiable set backed by the given set
190     * @throws IllegalArgumentException  if the set is null
191     */
192    public static <E> Set<E> unmodifiableSet(final Set<? extends E> set) {
193        return UnmodifiableSet.unmodifiableSet(set);
194    }
195
196    /**
197     * Returns a predicated (validating) set backed by the given set.
198     * <p>
199     * Only objects that pass the test in the given predicate can be added to the set.
200     * Trying to add an invalid object results in an IllegalArgumentException.
201     * It is important not to use the original set after invoking this method,
202     * as it is a backdoor for adding invalid objects.
203     *
204     * @param <E> the element type
205     * @param set  the set to predicate, must not be null
206     * @param predicate  the predicate for the set, must not be null
207     * @return a predicated set backed by the given set
208     * @throws IllegalArgumentException  if the Set or Predicate is null
209     */
210    public static <E> Set<E> predicatedSet(final Set<E> set, final Predicate<? super E> predicate) {
211        return PredicatedSet.predicatedSet(set, predicate);
212    }
213
214    /**
215     * Returns a transformed set backed by the given set.
216     * <p>
217     * Each object is passed through the transformer as it is added to the
218     * Set. It is important not to use the original set after invoking this
219     * method, as it is a backdoor for adding untransformed objects.
220     * <p>
221     * Existing entries in the specified set will not be transformed.
222     * If you want that behaviour, see {@link TransformedSet#transformedSet}.
223     *
224     * @param <E> the element type
225     * @param set  the set to transform, must not be null
226     * @param transformer  the transformer for the set, must not be null
227     * @return a transformed set backed by the given set
228     * @throws IllegalArgumentException  if the Set or Transformer is null
229     */
230    public static <E> Set<E> transformedSet(final Set<E> set, final Transformer<? super E, ? extends E> transformer) {
231        return TransformedSet.transformingSet(set, transformer);
232    }
233
234    /**
235     * Returns a set that maintains the order of elements that are added
236     * backed by the given set.
237     * <p>
238     * If an element is added twice, the order is determined by the first add.
239     * The order is observed through the iterator or toArray.
240     *
241     * @param <E> the element type
242     * @param set  the set to order, must not be null
243     * @return an ordered set backed by the given set
244     * @throws IllegalArgumentException  if the Set is null
245     */
246    public static <E> Set<E> orderedSet(final Set<E> set) {
247        return ListOrderedSet.listOrderedSet(set);
248    }
249
250    //-----------------------------------------------------------------------
251    /**
252     * Returns a synchronized sorted set backed by the given sorted set.
253     * <p>
254     * You must manually synchronize on the returned set's iterator to
255     * avoid non-deterministic behavior:
256     *
257     * <pre>
258     * Set s = SetUtils.synchronizedSet(mySet);
259     * synchronized (s) {
260     *     Iterator i = s.iterator();
261     *     while (i.hasNext()) {
262     *         process (i.next());
263     *     }
264     * }
265     * </pre>
266     *
267     * This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
268     *
269     * @param <E> the element type
270     * @param set  the sorted set to synchronize, must not be null
271     * @return a synchronized set backed by the given set
272     * @throws IllegalArgumentException  if the set is null
273     */
274    public static <E> SortedSet<E> synchronizedSortedSet(final SortedSet<E> set) {
275        return Collections.synchronizedSortedSet(set);
276    }
277
278    /**
279     * Returns an unmodifiable sorted set backed by the given sorted set.
280     * <p>
281     * This method uses the implementation in the decorators subpackage.
282     *
283     * @param <E> the element type
284     * @param set  the sorted set to make unmodifiable, must not be null
285     * @return an unmodifiable set backed by the given set
286     * @throws IllegalArgumentException  if the set is null
287     */
288    public static <E> SortedSet<E> unmodifiableSortedSet(final SortedSet<E> set) {
289        return UnmodifiableSortedSet.unmodifiableSortedSet(set);
290    }
291
292    /**
293     * Returns a predicated (validating) sorted set backed by the given sorted set.
294     * <p>
295     * Only objects that pass the test in the given predicate can be added to the set.
296     * Trying to add an invalid object results in an IllegalArgumentException.
297     * It is important not to use the original set after invoking this method,
298     * as it is a backdoor for adding invalid objects.
299     *
300     * @param <E> the element type
301     * @param set  the sorted set to predicate, must not be null
302     * @param predicate  the predicate for the sorted set, must not be null
303     * @return a predicated sorted set backed by the given sorted set
304     * @throws IllegalArgumentException  if the Set or Predicate is null
305     */
306    public static <E> SortedSet<E> predicatedSortedSet(final SortedSet<E> set, final Predicate<? super E> predicate) {
307        return PredicatedSortedSet.predicatedSortedSet(set, predicate);
308    }
309
310    /**
311     * Returns a transformed sorted set backed by the given set.
312     * <p>
313     * Each object is passed through the transformer as it is added to the
314     * Set. It is important not to use the original set after invoking this
315     * method, as it is a backdoor for adding untransformed objects.
316     * <p>
317     * Existing entries in the specified set will not be transformed.
318     * If you want that behaviour, see {@link TransformedSortedSet#transformedSortedSet}.
319     *
320     * @param <E> the element type
321     * @param set  the set to transform, must not be null
322     * @param transformer  the transformer for the set, must not be null
323     * @return a transformed set backed by the given set
324     * @throws IllegalArgumentException  if the Set or Transformer is null
325     */
326    public static <E> SortedSet<E> transformedSortedSet(final SortedSet<E> set,
327                                                        final Transformer<? super E, ? extends E> transformer) {
328        return TransformedSortedSet.transformingSortedSet(set, transformer);
329    }
330
331}