SetUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.collections4;

  18. import java.util.AbstractSet;
  19. import java.util.Arrays;
  20. import java.util.Collection;
  21. import java.util.Collections;
  22. import java.util.HashSet;
  23. import java.util.IdentityHashMap;
  24. import java.util.Iterator;
  25. import java.util.NavigableSet;
  26. import java.util.Objects;
  27. import java.util.Set;
  28. import java.util.SortedSet;
  29. import java.util.TreeSet;

  30. import org.apache.commons.collections4.set.ListOrderedSet;
  31. import org.apache.commons.collections4.set.PredicatedNavigableSet;
  32. import org.apache.commons.collections4.set.PredicatedSet;
  33. import org.apache.commons.collections4.set.PredicatedSortedSet;
  34. import org.apache.commons.collections4.set.TransformedNavigableSet;
  35. import org.apache.commons.collections4.set.TransformedSet;
  36. import org.apache.commons.collections4.set.TransformedSortedSet;
  37. import org.apache.commons.collections4.set.UnmodifiableNavigableSet;
  38. import org.apache.commons.collections4.set.UnmodifiableSet;
  39. import org.apache.commons.collections4.set.UnmodifiableSortedSet;

  40. /**
  41.  * Provides utility methods and decorators for
  42.  * {@link Set} and {@link SortedSet} instances.
  43.  *
  44.  * @since 2.1
  45.  */
  46. public class SetUtils {

  47.     /**
  48.      * An unmodifiable <strong>view</strong> of a set that may be backed by other sets.
  49.      * <p>
  50.      * If the decorated sets change, this view will change as well. The contents
  51.      * of this view can be transferred to another instance via the {@link #copyInto(Set)}
  52.      * and {@link #toSet()} methods.
  53.      * </p>
  54.      *
  55.      * @param <E> the element type
  56.      * @since 4.1
  57.      */
  58.     public abstract static class SetView<E> extends AbstractSet<E> {

  59.         /**
  60.          * Constructs a new instance.
  61.          */
  62.         public SetView() {
  63.             // empty
  64.         }

  65.         /**
  66.          * Copies the contents of this view into the provided set.
  67.          *
  68.          * @param <S> the set type
  69.          * @param set  the set for copying the contents
  70.          */
  71.         public <S extends Set<E>> void copyInto(final S set) {
  72.             CollectionUtils.addAll(set, this);
  73.         }

  74.         /**
  75.          * Return an iterator for this view; the returned iterator is
  76.          * not required to be unmodifiable.
  77.          * @return a new iterator for this view
  78.          */
  79.         protected abstract Iterator<E> createIterator();

  80.         @Override
  81.         public Iterator<E> iterator() {
  82.             return IteratorUtils.unmodifiableIterator(createIterator());
  83.         }

  84.         @Override
  85.         public int size() {
  86.             return IteratorUtils.size(iterator());
  87.         }

  88.         /**
  89.          * Returns a new set containing the contents of this view.
  90.          *
  91.          * @return a new set containing all elements of this view
  92.          */
  93.         public Set<E> toSet() {
  94.             final Set<E> set = new HashSet<>(size());
  95.             copyInto(set);
  96.             return set;
  97.         }
  98.     }

  99.     /**
  100.      * An empty unmodifiable sorted set.
  101.      * This is not provided in the JDK.
  102.      */
  103.     @SuppressWarnings("rawtypes")
  104.     public static final SortedSet EMPTY_SORTED_SET =
  105.             UnmodifiableSortedSet.unmodifiableSortedSet(new TreeSet<>());

  106.     /**
  107.      * Returns an unmodifiable <strong>view</strong> containing the difference of the given
  108.      * {@link Set}s, denoted by {@code a \ b} (or {@code a - b}).
  109.      * <p>
  110.      * The returned view contains all elements of {@code a} that are not a member
  111.      * of {@code b}.
  112.      * </p>
  113.      *
  114.      * @param <E> the generic type that is able to represent the types contained
  115.      *   in both input sets.
  116.      * @param setA  the set to subtract from, must not be null
  117.      * @param setB  the set to subtract, must not be null
  118.      * @return a view of the relative complement of the two sets
  119.      * @since 4.1
  120.      */
  121.     public static <E> SetView<E> difference(final Set<? extends E> setA, final Set<? extends E> setB) {
  122.         Objects.requireNonNull(setA, "setA");
  123.         Objects.requireNonNull(setB, "setB");

  124.         final Predicate<E> notContainedInB = object -> !setB.contains(object);

  125.         return new SetView<E>() {
  126.             @Override
  127.             public boolean contains(final Object o) {
  128.                 return setA.contains(o) && !setB.contains(o);
  129.             }

  130.             @Override
  131.             public Iterator<E> createIterator() {
  132.                 return IteratorUtils.filteredIterator(setA.iterator(), notContainedInB);
  133.             }
  134.         };
  135.     }

  136.     /**
  137.      * Returns an unmodifiable <strong>view</strong> of the symmetric difference of the given
  138.      * {@link Set}s.
  139.      * <p>
  140.      * The returned view contains all elements of {@code a} and {@code b} that are
  141.      * not a member of the other set.
  142.      * </p>
  143.      * <p>
  144.      * This is equivalent to {@code union(difference(a, b), difference(b, a))}.
  145.      * </p>
  146.      *
  147.      * @param <E> the generic type that is able to represent the types contained
  148.      *   in both input sets.
  149.      * @param setA  the first set, must not be null
  150.      * @param setB  the second set, must not be null
  151.      * @return a view of the symmetric difference of the two sets
  152.      * @since 4.1
  153.      */
  154.     public static <E> SetView<E> disjunction(final Set<? extends E> setA, final Set<? extends E> setB) {
  155.         Objects.requireNonNull(setA, "setA");
  156.         Objects.requireNonNull(setB, "setB");

  157.         final SetView<E> aMinusB = difference(setA, setB);
  158.         final SetView<E> bMinusA = difference(setB, setA);

  159.         return new SetView<E>() {
  160.             @Override
  161.             public boolean contains(final Object o) {
  162.                 return setA.contains(o) ^ setB.contains(o);
  163.             }

  164.             @Override
  165.             public Iterator<E> createIterator() {
  166.                 return IteratorUtils.chainedIterator(aMinusB.iterator(), bMinusA.iterator());
  167.             }

  168.             @Override
  169.             public boolean isEmpty() {
  170.                 return aMinusB.isEmpty() && bMinusA.isEmpty();
  171.             }

  172.             @Override
  173.             public int size() {
  174.                 return aMinusB.size() + bMinusA.size();
  175.             }
  176.         };
  177.     }

  178.     /**
  179.      * Returns an immutable empty set if the argument is {@code null},
  180.      * or the argument itself otherwise.
  181.      *
  182.      * @param <T> the element type
  183.      * @param set the set, possibly {@code null}
  184.      * @return an empty set if the argument is {@code null}
  185.      */
  186.     public static <T> Set<T> emptyIfNull(final Set<T> set) {
  187.         return set == null ? Collections.<T>emptySet() : set;
  188.     }

  189.     /**
  190.      * Gets a typed empty unmodifiable Set.
  191.      *
  192.      * @param <E> the element type
  193.      * @return an empty Set
  194.      */
  195.     public static <E> Set<E> emptySet() {
  196.         return Collections.<E>emptySet();
  197.     }

  198.     /**
  199.      * Gets a typed empty unmodifiable sorted set.
  200.      *
  201.      * @param <E> the element type
  202.      * @return an empty sorted Set
  203.      */
  204.     @SuppressWarnings("unchecked") // empty set is OK for any type
  205.     public static <E> SortedSet<E> emptySortedSet() {
  206.         return EMPTY_SORTED_SET;
  207.     }

  208.     /**
  209.      * Generates a hash code using the algorithm specified in
  210.      * {@link java.util.Set#hashCode()}.
  211.      * <p>
  212.      * This method is useful for implementing {@code Set} when you cannot
  213.      * extend AbstractSet. The method takes Collection instances to enable other
  214.      * collection types to use the Set implementation algorithm.
  215.      * </p>
  216.      *
  217.      * @param <T> the element type
  218.      * @see java.util.Set#hashCode()
  219.      * @param set  the set to calculate the hash code for, may be null
  220.      * @return the hash code
  221.      */
  222.     public static <T> int hashCodeForSet(final Collection<T> set) {
  223.         if (set == null) {
  224.             return 0;
  225.         }

  226.         int hashCode = 0;
  227.         for (final T obj : set) {
  228.             if (obj != null) {
  229.                 hashCode += obj.hashCode();
  230.             }
  231.         }
  232.         return hashCode;
  233.     }

  234.     /**
  235.      * Creates a set from the given items. If the passed var-args argument is {@code
  236.      * null}, then the method returns {@code null}.
  237.      *
  238.      * @param <E> the element type
  239.      * @param items the elements that make up the new set
  240.      * @return a set
  241.      * @since 4.3
  242.      */
  243.     public static <E> HashSet<E> hashSet(final E... items) {
  244.         if (items == null) {
  245.             return null;
  246.         }
  247.         return new HashSet<>(Arrays.asList(items));
  248.     }

  249.     /**
  250.      * Returns an unmodifiable <strong>view</strong> of the intersection of the given {@link Set}s.
  251.      * <p>
  252.      * The returned view contains all elements that are members of both input sets
  253.      * ({@code a} and {@code b}).
  254.      * </p>
  255.      *
  256.      * @param <E> the generic type that is able to represent the types contained
  257.      *   in both input sets.
  258.      * @param setA  the first set, must not be null
  259.      * @param setB  the second set, must not be null
  260.      * @return a view of the intersection of the two sets
  261.      * @since 4.1
  262.      */
  263.     public static <E> SetView<E> intersection(final Set<? extends E> setA, final Set<? extends E> setB) {
  264.         Objects.requireNonNull(setA, "setA");
  265.         Objects.requireNonNull(setB, "setB");

  266.         return new SetView<E>() {
  267.             @Override
  268.             public boolean contains(final Object o) {
  269.                 return setA.contains(o) && setB.contains(o);
  270.             }

  271.             @Override
  272.             public Iterator<E> createIterator() {
  273.                 return IteratorUtils.filteredIterator(setA.iterator(), setB::contains);
  274.             }
  275.         };
  276.     }

  277.     /**
  278.      * Tests two sets for equality as per the {@code equals()} contract
  279.      * in {@link java.util.Set#equals(Object)}.
  280.      * <p>
  281.      * This method is useful for implementing {@code Set} when you cannot
  282.      * extend AbstractSet. The method takes Collection instances to enable other
  283.      * collection types to use the Set implementation algorithm.
  284.      * </p>
  285.      * <p>
  286.      * The relevant text (slightly paraphrased as this is a static method) is:
  287.      * </p>
  288.      * <blockquote>
  289.      * <p>Two sets are considered equal if they have
  290.      * the same size, and every member of the first set is contained in
  291.      * the second. This ensures that the {@code equals} method works
  292.      * properly across different implementations of the {@code Set}
  293.      * interface.
  294.      * </p>
  295.      * <p>
  296.      * This implementation first checks if the two sets are the same object:
  297.      * if so it returns {@code true}.  Then, it checks if the two sets are
  298.      * identical in size; if not, it returns false. If so, it returns
  299.      * {@code a.containsAll((Collection) b)}.
  300.      * </p>
  301.      * </blockquote>
  302.      *
  303.      * @see java.util.Set
  304.      * @param set1  the first set, may be null
  305.      * @param set2  the second set, may be null
  306.      * @return whether the sets are equal by value comparison
  307.      */
  308.     public static boolean isEqualSet(final Collection<?> set1, final Collection<?> set2) {
  309.         if (set1 == set2) {
  310.             return true;
  311.         }
  312.         if (set1 == null || set2 == null || set1.size() != set2.size()) {
  313.             return false;
  314.         }

  315.         return set1.containsAll(set2);
  316.     }

  317.     /**
  318.      * Returns a new hash set that matches elements based on {@code ==} not
  319.      * {@code equals()}.
  320.      * <p>
  321.      * <strong>This set will violate the detail of various Set contracts.</strong>
  322.      * As a general rule, don't compare this set to other sets. In particular, you can't
  323.      * use decorators like {@link ListOrderedSet} on it, which silently assume that these
  324.      * contracts are fulfilled.
  325.      * </p>
  326.      * <p>
  327.      * <strong>Note that the returned set is not synchronized and is not thread-safe.</strong>
  328.      * If you wish to use this set from multiple threads concurrently, you must use
  329.      * appropriate synchronization. The simplest approach is to wrap this map
  330.      * using {@link java.util.Collections#synchronizedSet(Set)}. This class may throw
  331.      * exceptions when accessed by concurrent threads without synchronization.
  332.      * </p>
  333.      *
  334.      * @param <E>  the element type
  335.      * @return a new identity hash set
  336.      * @since 4.1
  337.      */
  338.     public static <E> Set<E> newIdentityHashSet() {
  339.         return Collections.newSetFromMap(new IdentityHashMap<>());
  340.     }

  341.     /**
  342.      * Returns a set that maintains the order of elements that are added
  343.      * backed by the given set.
  344.      * <p>
  345.      * If an element is added twice, the order is determined by the first add.
  346.      * The order is observed through the iterator or toArray.
  347.      * </p>
  348.      *
  349.      * @param <E> the element type
  350.      * @param set  the set to order, must not be null
  351.      * @return an ordered set backed by the given set
  352.      * @throws NullPointerException if the set is null
  353.      */
  354.     public static <E> Set<E> orderedSet(final Set<E> set) {
  355.         return ListOrderedSet.listOrderedSet(set);
  356.     }

  357.     /**
  358.      * Returns a predicated (validating) navigable set backed by the given navigable set.
  359.      * <p>
  360.      * Only objects that pass the test in the given predicate can be added to the set.
  361.      * Trying to add an invalid object results in an IllegalArgumentException.
  362.      * It is important not to use the original set after invoking this method,
  363.      * as it is a backdoor for adding invalid objects.
  364.      * </p>
  365.      *
  366.      * @param <E> the element type
  367.      * @param set  the navigable set to predicate, must not be null
  368.      * @param predicate  the predicate for the navigable set, must not be null
  369.      * @return a predicated navigable set backed by the given navigable set
  370.      * @throws NullPointerException if the set or predicate is null
  371.      * @since 4.1
  372.      */
  373.     public static <E> SortedSet<E> predicatedNavigableSet(final NavigableSet<E> set,
  374.                                                           final Predicate<? super E> predicate) {
  375.         return PredicatedNavigableSet.predicatedNavigableSet(set, predicate);
  376.     }

  377.     /**
  378.      * Returns a predicated (validating) set backed by the given set.
  379.      * <p>
  380.      * Only objects that pass the test in the given predicate can be added to the set.
  381.      * Trying to add an invalid object results in an IllegalArgumentException.
  382.      * It is important not to use the original set after invoking this method,
  383.      * as it is a backdoor for adding invalid objects.
  384.      * </p>
  385.      *
  386.      * @param <E> the element type
  387.      * @param set  the set to predicate, must not be null
  388.      * @param predicate  the predicate for the set, must not be null
  389.      * @return a predicated set backed by the given set
  390.      * @throws NullPointerException if the set or predicate is null
  391.      */
  392.     public static <E> Set<E> predicatedSet(final Set<E> set, final Predicate<? super E> predicate) {
  393.         return PredicatedSet.predicatedSet(set, predicate);
  394.     }

  395.     /**
  396.      * Returns a predicated (validating) sorted set backed by the given sorted set.
  397.      * <p>
  398.      * Only objects that pass the test in the given predicate can be added to the set.
  399.      * Trying to add an invalid object results in an IllegalArgumentException.
  400.      * It is important not to use the original set after invoking this method,
  401.      * as it is a backdoor for adding invalid objects.
  402.      * </p>
  403.      *
  404.      * @param <E> the element type
  405.      * @param set  the sorted set to predicate, must not be null
  406.      * @param predicate  the predicate for the sorted set, must not be null
  407.      * @return a predicated sorted set backed by the given sorted set
  408.      * @throws NullPointerException if the set or predicate is null
  409.      */
  410.     public static <E> SortedSet<E> predicatedSortedSet(final SortedSet<E> set,
  411.                                                        final Predicate<? super E> predicate) {
  412.         return PredicatedSortedSet.predicatedSortedSet(set, predicate);
  413.     }

  414.     /**
  415.      * Returns a synchronized set backed by the given set.
  416.      * <p>
  417.      * You must manually synchronize on the returned set's iterator to
  418.      * avoid non-deterministic behavior:
  419.      * </p>
  420.      *
  421.      * <pre>
  422.      * Sets s = SetUtils.synchronizedSet(mySet);
  423.      * synchronized (s) {
  424.      *     Iterator i = s.iterator();
  425.      *     while (i.hasNext()) {
  426.      *         process (i.next());
  427.      *     }
  428.      * }
  429.      * </pre>
  430.      *
  431.      * <p>
  432.      * This method is just a wrapper for {@link Collections#synchronizedSet(Set)}.
  433.      * </p>
  434.      *
  435.      * @param <E> the element type
  436.      * @param set  the set to synchronize, must not be null
  437.      * @return a synchronized set backed by the given set
  438.      * @throws NullPointerException if the set is null
  439.      */
  440.     public static <E> Set<E> synchronizedSet(final Set<E> set) {
  441.         return Collections.synchronizedSet(set);
  442.     }

  443.     // SortedSet
  444.     /**
  445.      * Returns a synchronized sorted set backed by the given sorted set.
  446.      * <p>
  447.      * You must manually synchronize on the returned set's iterator to
  448.      * avoid non-deterministic behavior:
  449.      * </p>
  450.      *
  451.      * <pre>
  452.      * Set s = SetUtils.synchronizedSortedSet(mySet);
  453.      * synchronized (s) {
  454.      *     Iterator i = s.iterator();
  455.      *     while (i.hasNext()) {
  456.      *         process (i.next());
  457.      *     }
  458.      * }
  459.      * </pre>
  460.      *
  461.      * <p>
  462.      * This method is just a wrapper for {@link Collections#synchronizedSortedSet(SortedSet)}.
  463.      * </p>
  464.      *
  465.      * @param <E> the element type
  466.      * @param set  the sorted set to synchronize, must not be null
  467.      * @return a synchronized set backed by the given set
  468.      * @throws NullPointerException if the set is null
  469.      */
  470.     public static <E> SortedSet<E> synchronizedSortedSet(final SortedSet<E> set) {
  471.         return Collections.synchronizedSortedSet(set);
  472.     }

  473.     /**
  474.      * Returns a transformed navigable set backed by the given navigable set.
  475.      * <p>
  476.      * Each object is passed through the transformer as it is added to the
  477.      * Set. It is important not to use the original set after invoking this
  478.      * method, as it is a backdoor for adding untransformed objects.
  479.      * </p>
  480.      * <p>
  481.      * Existing entries in the specified set will not be transformed.
  482.      * If you want that behavior, see {@link TransformedNavigableSet#transformedNavigableSet}.
  483.      * </p>
  484.      *
  485.      * @param <E> the element type
  486.      * @param set  the navigable set to transform, must not be null
  487.      * @param transformer  the transformer for the set, must not be null
  488.      * @return a transformed set backed by the given set
  489.      * @throws NullPointerException if the set or transformer is null
  490.      * @since 4.1
  491.      */
  492.     public static <E> SortedSet<E> transformedNavigableSet(final NavigableSet<E> set,
  493.                                                            final Transformer<? super E, ? extends E> transformer) {
  494.         return TransformedNavigableSet.transformingNavigableSet(set, transformer);
  495.     }

  496.     /**
  497.      * Returns a transformed set backed by the given set.
  498.      * <p>
  499.      * Each object is passed through the transformer as it is added to the
  500.      * Set. It is important not to use the original set after invoking this
  501.      * method, as it is a backdoor for adding untransformed objects.
  502.      * </p>
  503.      * <p>
  504.      * Existing entries in the specified set will not be transformed.
  505.      * If you want that behavior, see {@link TransformedSet#transformedSet}.
  506.      * </p>
  507.      *
  508.      * @param <E> the element type
  509.      * @param set  the set to transform, must not be null
  510.      * @param transformer  the transformer for the set, must not be null
  511.      * @return a transformed set backed by the given set
  512.      * @throws NullPointerException if the set or transformer is null
  513.      */
  514.     public static <E> Set<E> transformedSet(final Set<E> set,
  515.                                             final Transformer<? super E, ? extends E> transformer) {
  516.         return TransformedSet.transformingSet(set, transformer);
  517.     }

  518.     /**
  519.      * Returns a transformed sorted set backed by the given set.
  520.      * <p>
  521.      * Each object is passed through the transformer as it is added to the
  522.      * Set. It is important not to use the original set after invoking this
  523.      * method, as it is a backdoor for adding untransformed objects.
  524.      * </p>
  525.      * <p>
  526.      * Existing entries in the specified set will not be transformed.
  527.      * If you want that behavior, see {@link TransformedSortedSet#transformedSortedSet}.
  528.      * </p>
  529.      *
  530.      * @param <E> the element type
  531.      * @param set  the set to transform, must not be null
  532.      * @param transformer  the transformer for the set, must not be null
  533.      * @return a transformed set backed by the given set
  534.      * @throws NullPointerException if the set or transformer is null
  535.      */
  536.     public static <E> SortedSet<E> transformedSortedSet(final SortedSet<E> set,
  537.                                                         final Transformer<? super E, ? extends E> transformer) {
  538.         return TransformedSortedSet.transformingSortedSet(set, transformer);
  539.     }

  540.     // Set operations

  541.     /**
  542.      * Returns an unmodifiable <strong>view</strong> of the union of the given {@link Set}s.
  543.      * <p>
  544.      * The returned view contains all elements of {@code a} and {@code b}.
  545.      * </p>
  546.      *
  547.      * @param <E> the generic type that is able to represent the types contained
  548.      *   in both input sets.
  549.      * @param setA  the first set, must not be null
  550.      * @param setB  the second set, must not be null
  551.      * @return a view of the union of the two set
  552.      * @throws NullPointerException if either input set is null
  553.      * @since 4.1
  554.      */
  555.     public static <E> SetView<E> union(final Set<? extends E> setA, final Set<? extends E> setB) {
  556.         Objects.requireNonNull(setA, "setA");
  557.         Objects.requireNonNull(setB, "setB");

  558.         final SetView<E> bMinusA = difference(setB, setA);

  559.         return new SetView<E>() {
  560.             @Override
  561.             public boolean contains(final Object o) {
  562.                 return setA.contains(o) || setB.contains(o);
  563.             }

  564.             @Override
  565.             public Iterator<E> createIterator() {
  566.                 return IteratorUtils.chainedIterator(setA.iterator(), bMinusA.iterator());
  567.             }

  568.             @Override
  569.             public boolean isEmpty() {
  570.                 return setA.isEmpty() && setB.isEmpty();
  571.             }

  572.             @Override
  573.             public int size() {
  574.                 return setA.size() + bMinusA.size();
  575.             }
  576.         };
  577.     }

  578.     /**
  579.      * Returns an unmodifiable navigable set backed by the given navigable set.
  580.      * <p>
  581.      * This method uses the implementation in the decorators subpackage.
  582.      * </p>
  583.      *
  584.      * @param <E> the element type
  585.      * @param set  the navigable set to make unmodifiable, must not be null
  586.      * @return an unmodifiable set backed by the given set
  587.      * @throws NullPointerException if the set is null
  588.      * @since 4.1
  589.      */
  590.     public static <E> SortedSet<E> unmodifiableNavigableSet(final NavigableSet<E> set) {
  591.         return UnmodifiableNavigableSet.unmodifiableNavigableSet(set);
  592.     }

  593.     /**
  594.      * Creates an unmodifiable set from the given items. If the passed var-args argument is {@code
  595.      * null}, then the method returns {@code null}.
  596.      * @param <E> the element type
  597.      * @param items the elements that make up the new set
  598.      * @return a set
  599.      * @since 4.3
  600.      */
  601.     public static <E> Set<E> unmodifiableSet(final E... items) {
  602.         if (items == null) {
  603.             return null;
  604.         }
  605.         return UnmodifiableSet.unmodifiableSet(hashSet(items));
  606.     }

  607.     /**
  608.      * Returns an unmodifiable set backed by the given set.
  609.      * <p>
  610.      * This method uses the implementation in the decorators subpackage.
  611.      * </p>
  612.      *
  613.      * @param <E> the element type
  614.      * @param set  the set to make unmodifiable, must not be null
  615.      * @return an unmodifiable set backed by the given set
  616.      * @throws NullPointerException if the set is null
  617.      */
  618.     public static <E> Set<E> unmodifiableSet(final Set<? extends E> set) {
  619.         return UnmodifiableSet.unmodifiableSet(set);
  620.     }

  621.     /**
  622.      * Returns an unmodifiable sorted set backed by the given sorted set.
  623.      * <p>
  624.      * This method uses the implementation in the decorators subpackage.
  625.      * </p>
  626.      *
  627.      * @param <E> the element type
  628.      * @param set  the sorted set to make unmodifiable, must not be null
  629.      * @return an unmodifiable set backed by the given set
  630.      * @throws NullPointerException if the set is null
  631.      */
  632.     public static <E> SortedSet<E> unmodifiableSortedSet(final SortedSet<E> set) {
  633.         return UnmodifiableSortedSet.unmodifiableSortedSet(set);
  634.     }

  635.     /**
  636.      * Don't allow instances.
  637.      */
  638.     private SetUtils() {
  639.         // empty
  640.     }

  641. }