1. /*
  2. * Copyright 2002-2004 The Apache Software Foundation
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License");
  5. * you may not use this file except in compliance with the License.
  6. * You may obtain a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS,
  12. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. * See the License for the specific language governing permissions and
  14. * limitations under the License.
  15. */
  16. package org.apache.commons.collections;
  17. import java.util.Collection;
  18. import java.util.Collections;
  19. import java.util.Iterator;
  20. import java.util.Set;
  21. import java.util.SortedSet;
  22. import java.util.TreeSet;
  23. import org.apache.commons.collections.set.ListOrderedSet;
  24. import org.apache.commons.collections.set.PredicatedSet;
  25. import org.apache.commons.collections.set.PredicatedSortedSet;
  26. import org.apache.commons.collections.set.SynchronizedSet;
  27. import org.apache.commons.collections.set.SynchronizedSortedSet;
  28. import org.apache.commons.collections.set.TransformedSet;
  29. import org.apache.commons.collections.set.TransformedSortedSet;
  30. import org.apache.commons.collections.set.TypedSet;
  31. import org.apache.commons.collections.set.TypedSortedSet;
  32. import org.apache.commons.collections.set.UnmodifiableSet;
  33. import org.apache.commons.collections.set.UnmodifiableSortedSet;
  34. /**
  35. * Provides utility methods and decorators for
  36. * {@link Set} and {@link SortedSet} instances.
  37. *
  38. * @since Commons Collections 2.1
  39. * @version $Revision: 1.26 $ $Date: 2004/04/01 20:12:00 $
  40. *
  41. * @author Paul Jack
  42. * @author Stephen Colebourne
  43. * @author Neil O'Toole
  44. * @author Matthew Hawthorne
  45. */
  46. public class SetUtils {
  47. /**
  48. * An empty unmodifiable set.
  49. * This uses the {@link Collections} implementation
  50. * and is provided for completeness.
  51. */
  52. public static final Set EMPTY_SET = Collections.EMPTY_SET;
  53. /**
  54. * An empty unmodifiable sorted set.
  55. * This is not provided in the JDK.
  56. */
  57. public static final SortedSet EMPTY_SORTED_SET = UnmodifiableSortedSet.decorate(new TreeSet());
  58. /**
  59. * <code>SetUtils</code> should not normally be instantiated.
  60. */
  61. public SetUtils() {
  62. }
  63. //-----------------------------------------------------------------------
  64. /**
  65. * Tests two sets for equality as per the <code>equals()</code> contract
  66. * in {@link java.util.Set#equals(java.lang.Object)}.
  67. * <p>
  68. * This method is useful for implementing <code>Set</code> when you cannot
  69. * extend AbstractSet. The method takes Collection instances to enable other
  70. * collection types to use the Set implementation algorithm.
  71. * <p>
  72. * The relevant text (slightly paraphrased as this is a static method) is:
  73. * <blockquote>
  74. * <p>Two sets are considered equal if they have
  75. * the same size, and every member of the first set is contained in
  76. * the second. This ensures that the <tt>equals</tt> method works
  77. * properly across different implementations of the <tt>Set</tt>
  78. * interface.</p>
  79. *
  80. * <p>
  81. * This implementation first checks if the two sets are the same object:
  82. * if so it returns <tt>true</tt>. Then, it checks if the two sets are
  83. * identical in size; if not, it returns false. If so, it returns
  84. * <tt>a.containsAll((Collection) b)</tt>.</p>
  85. * </blockquote>
  86. *
  87. * @see java.util.Set
  88. * @param set1 the first set, may be null
  89. * @param set2 the second set, may be null
  90. * @return whether the sets are equal by value comparison
  91. */
  92. public static boolean isEqualSet(final Collection set1, final Collection set2) {
  93. if (set1 == set2) {
  94. return true;
  95. }
  96. if (set1 == null || set2 == null || set1.size() != set2.size()) {
  97. return false;
  98. }
  99. return set1.containsAll(set2);
  100. }
  101. /**
  102. * Generates a hash code using the algorithm specified in
  103. * {@link java.util.Set#hashCode()}.
  104. * <p>
  105. * This method is useful for implementing <code>Set</code> when you cannot
  106. * extend AbstractSet. The method takes Collection instances to enable other
  107. * collection types to use the Set implementation algorithm.
  108. *
  109. * @see java.util.Set#hashCode()
  110. * @param set the set to calculate the hash code for, may be null
  111. * @return the hash code
  112. */
  113. public static int hashCodeForSet(final Collection set) {
  114. if (set == null) {
  115. return 0;
  116. }
  117. int hashCode = 0;
  118. Iterator it = set.iterator();
  119. Object obj = null;
  120. while (it.hasNext()) {
  121. obj = it.next();
  122. if (obj != null) {
  123. hashCode += obj.hashCode();
  124. }
  125. }
  126. return hashCode;
  127. }
  128. //-----------------------------------------------------------------------
  129. /**
  130. * Returns a synchronized set backed by the given set.
  131. * <p>
  132. * You must manually synchronize on the returned buffer's iterator to
  133. * avoid non-deterministic behavior:
  134. *
  135. * <pre>
  136. * Set s = SetUtils.synchronizedSet(mySet);
  137. * synchronized (s) {
  138. * Iterator i = s.iterator();
  139. * while (i.hasNext()) {
  140. * process (i.next());
  141. * }
  142. * }
  143. * </pre>
  144. *
  145. * This method uses the implementation in the decorators subpackage.
  146. *
  147. * @param set the set to synchronize, must not be null
  148. * @return a synchronized set backed by the given set
  149. * @throws IllegalArgumentException if the set is null
  150. */
  151. public static Set synchronizedSet(Set set) {
  152. return SynchronizedSet.decorate(set);
  153. }
  154. /**
  155. * Returns an unmodifiable set backed by the given set.
  156. * <p>
  157. * This method uses the implementation in the decorators subpackage.
  158. *
  159. * @param set the set to make unmodifiable, must not be null
  160. * @return an unmodifiable set backed by the given set
  161. * @throws IllegalArgumentException if the set is null
  162. */
  163. public static Set unmodifiableSet(Set set) {
  164. return UnmodifiableSet.decorate(set);
  165. }
  166. /**
  167. * Returns a predicated (validating) set backed by the given set.
  168. * <p>
  169. * Only objects that pass the test in the given predicate can be added to the set.
  170. * Trying to add an invalid object results in an IllegalArgumentException.
  171. * It is important not to use the original set after invoking this method,
  172. * as it is a backdoor for adding invalid objects.
  173. *
  174. * @param set the set to predicate, must not be null
  175. * @param predicate the predicate for the set, must not be null
  176. * @return a predicated set backed by the given set
  177. * @throws IllegalArgumentException if the Set or Predicate is null
  178. */
  179. public static Set predicatedSet(Set set, Predicate predicate) {
  180. return PredicatedSet.decorate(set, predicate);
  181. }
  182. /**
  183. * Returns a typed set backed by the given set.
  184. * <p>
  185. * Only objects of the specified type can be added to the set.
  186. *
  187. * @param set the set to limit to a specific type, must not be null
  188. * @param type the type of objects which may be added to the set
  189. * @return a typed set backed by the specified set
  190. */
  191. public static Set typedSet(Set set, Class type) {
  192. return TypedSet.decorate(set, type);
  193. }
  194. /**
  195. * Returns a transformed set backed by the given set.
  196. * <p>
  197. * Each object is passed through the transformer as it is added to the
  198. * Set. It is important not to use the original set after invoking this
  199. * method, as it is a backdoor for adding untransformed objects.
  200. *
  201. * @param set the set to transform, must not be null
  202. * @param transformer the transformer for the set, must not be null
  203. * @return a transformed set backed by the given set
  204. * @throws IllegalArgumentException if the Set or Transformer is null
  205. */
  206. public static Set transformedSet(Set set, Transformer transformer) {
  207. return TransformedSet.decorate(set, transformer);
  208. }
  209. /**
  210. * Returns a set that maintains the order of elements that are added
  211. * backed by the given set.
  212. * <p>
  213. * If an element is added twice, the order is determined by the first add.
  214. * The order is observed through the iterator or toArray.
  215. *
  216. * @param set the set to order, must not be null
  217. * @return an ordered set backed by the given set
  218. * @throws IllegalArgumentException if the Set is null
  219. */
  220. public static Set orderedSet(Set set) {
  221. return ListOrderedSet.decorate(set);
  222. }
  223. //-----------------------------------------------------------------------
  224. /**
  225. * Returns a synchronized sorted set backed by the given sorted set.
  226. * <p>
  227. * You must manually synchronize on the returned buffer's iterator to
  228. * avoid non-deterministic behavior:
  229. *
  230. * <pre>
  231. * Set s = SetUtils.synchronizedSet(mySet);
  232. * synchronized (s) {
  233. * Iterator i = s.iterator();
  234. * while (i.hasNext()) {
  235. * process (i.next());
  236. * }
  237. * }
  238. * </pre>
  239. *
  240. * This method uses the implementation in the decorators subpackage.
  241. *
  242. * @param set the sorted set to synchronize, must not be null
  243. * @return a synchronized set backed by the given set
  244. * @throws IllegalArgumentException if the set is null
  245. */
  246. public static SortedSet synchronizedSortedSet(SortedSet set) {
  247. return SynchronizedSortedSet.decorate(set);
  248. }
  249. /**
  250. * Returns an unmodifiable sorted set backed by the given sorted set.
  251. * <p>
  252. * This method uses the implementation in the decorators subpackage.
  253. *
  254. * @param set the sorted set to make unmodifiable, must not be null
  255. * @return an unmodifiable set backed by the given set
  256. * @throws IllegalArgumentException if the set is null
  257. */
  258. public static SortedSet unmodifiableSortedSet(SortedSet set) {
  259. return UnmodifiableSortedSet.decorate(set);
  260. }
  261. /**
  262. * Returns a predicated (validating) sorted set backed by the given sorted set.
  263. * <p>
  264. * Only objects that pass the test in the given predicate can be added to the set.
  265. * Trying to add an invalid object results in an IllegalArgumentException.
  266. * It is important not to use the original set after invoking this method,
  267. * as it is a backdoor for adding invalid objects.
  268. *
  269. * @param set the sorted set to predicate, must not be null
  270. * @param predicate the predicate for the sorted set, must not be null
  271. * @return a predicated sorted set backed by the given sorted set
  272. * @throws IllegalArgumentException if the Set or Predicate is null
  273. */
  274. public static SortedSet predicatedSortedSet(SortedSet set, Predicate predicate) {
  275. return PredicatedSortedSet.decorate(set, predicate);
  276. }
  277. /**
  278. * Returns a typed sorted set backed by the given set.
  279. * <p>
  280. * Only objects of the specified type can be added to the set.
  281. *
  282. * @param set the set to limit to a specific type, must not be null
  283. * @param type the type of objects which may be added to the set
  284. * @return a typed set backed by the specified set
  285. */
  286. public static SortedSet typedSortedSet(SortedSet set, Class type) {
  287. return TypedSortedSet.decorate(set, type);
  288. }
  289. /**
  290. * Returns a transformed sorted set backed by the given set.
  291. * <p>
  292. * Each object is passed through the transformer as it is added to the
  293. * Set. It is important not to use the original set after invoking this
  294. * method, as it is a backdoor for adding untransformed objects.
  295. *
  296. * @param set the set to transform, must not be null
  297. * @param transformer the transformer for the set, must not be null
  298. * @return a transformed set backed by the given set
  299. * @throws IllegalArgumentException if the Set or Transformer is null
  300. */
  301. public static SortedSet transformedSortedSet(SortedSet set, Transformer transformer) {
  302. return TransformedSortedSet.decorate(set, transformer);
  303. }
  304. }