1. /*
  2. * Copyright 2001-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.ArrayList;
  18. import java.util.Collection;
  19. import java.util.Collections;
  20. import java.util.Iterator;
  21. import java.util.List;
  22. import org.apache.commons.collections.list.FixedSizeList;
  23. import org.apache.commons.collections.list.LazyList;
  24. import org.apache.commons.collections.list.PredicatedList;
  25. import org.apache.commons.collections.list.SynchronizedList;
  26. import org.apache.commons.collections.list.TransformedList;
  27. import org.apache.commons.collections.list.TypedList;
  28. import org.apache.commons.collections.list.UnmodifiableList;
  29. /**
  30. * Provides utility methods and decorators for {@link List} instances.
  31. *
  32. * @since Commons Collections 1.0
  33. * @version $Revision: 1.28 $ $Date: 2004/04/01 20:12:00 $
  34. *
  35. * @author Federico Barbieri
  36. * @author Peter Donald
  37. * @author Paul Jack
  38. * @author Stephen Colebourne
  39. * @author Neil O'Toole
  40. * @author Matthew Hawthorne
  41. */
  42. public class ListUtils {
  43. /**
  44. * An empty unmodifiable list.
  45. * This uses the {@link Collections Collections} implementation
  46. * and is provided for completeness.
  47. */
  48. public static final List EMPTY_LIST = Collections.EMPTY_LIST;
  49. /**
  50. * <code>ListUtils</code> should not normally be instantiated.
  51. */
  52. public ListUtils() {
  53. }
  54. //-----------------------------------------------------------------------
  55. /**
  56. * Returns a new list containing all elements that are contained in
  57. * both given lists.
  58. *
  59. * @param list1 the first list
  60. * @param list2 the second list
  61. * @return the intersection of those two lists
  62. * @throws NullPointerException if either list is null
  63. */
  64. public static List intersection(final List list1, final List list2) {
  65. final ArrayList result = new ArrayList();
  66. final Iterator iterator = list2.iterator();
  67. while (iterator.hasNext()) {
  68. final Object o = iterator.next();
  69. if (list1.contains(o)) {
  70. result.add(o);
  71. }
  72. }
  73. return result;
  74. }
  75. /**
  76. * Subtracts all elements in the second list from the first list,
  77. * placing the results in a new list.
  78. * <p>
  79. * This differs from {@link List#removeAll(Collection)} in that
  80. * cardinality is respected; if <Code>list1</Code> contains two
  81. * occurrences of <Code>null</Code> and <Code>list2</Code> only
  82. * contains one occurrence, then the returned list will still contain
  83. * one occurrence.
  84. *
  85. * @param list1 the list to subtract from
  86. * @param list2 the list to subtract
  87. * @return a new list containing the results
  88. * @throws NullPointerException if either list is null
  89. */
  90. public static List subtract(final List list1, final List list2) {
  91. final ArrayList result = new ArrayList(list1);
  92. final Iterator iterator = list2.iterator();
  93. while (iterator.hasNext()) {
  94. result.remove(iterator.next());
  95. }
  96. return result;
  97. }
  98. /**
  99. * Returns the sum of the given lists. This is their intersection
  100. * subtracted from their union.
  101. *
  102. * @param list1 the first list
  103. * @param list2 the second list
  104. * @return a new list containing the sum of those lists
  105. * @throws NullPointerException if either list is null
  106. */
  107. public static List sum(final List list1, final List list2) {
  108. return subtract(union(list1, list2), intersection(list1, list2));
  109. }
  110. /**
  111. * Returns a new list containing the second list appended to the
  112. * first list. The {@link List#addAll(Collection)} operation is
  113. * used to append the two given lists into a new list.
  114. *
  115. * @param list1 the first list
  116. * @param list2 the second list
  117. * @return a new list containing the union of those lists
  118. * @throws NullPointerException if either list is null
  119. */
  120. public static List union(final List list1, final List list2) {
  121. final ArrayList result = new ArrayList(list1);
  122. result.addAll(list2);
  123. return result;
  124. }
  125. /**
  126. * Tests two lists for value-equality as per the equality contract in
  127. * {@link java.util.List#equals(java.lang.Object)}.
  128. * <p>
  129. * This method is useful for implementing <code>List</code> when you cannot
  130. * extend AbstractList. The method takes Collection instances to enable other
  131. * collection types to use the List implementation algorithm.
  132. * <p>
  133. * The relevant text (slightly paraphrased as this is a static method) is:
  134. * <blockquote>
  135. * Compares the two list objects for equality. Returns
  136. * <tt>true</tt> if and only if both
  137. * lists have the same size, and all corresponding pairs of elements in
  138. * the two lists are <i>equal</i>. (Two elements <tt>e1</tt> and
  139. * <tt>e2</tt> are <i>equal</i> if <tt>(e1==null ? e2==null :
  140. * e1.equals(e2))</tt>.) In other words, two lists are defined to be
  141. * equal if they contain the same elements in the same order. This
  142. * definition ensures that the equals method works properly across
  143. * different implementations of the <tt>List</tt> interface.
  144. * </blockquote>
  145. *
  146. * <b>Note:</b> The behaviour of this method is undefined if the lists are
  147. * modified during the equals comparison.
  148. *
  149. * @see java.util.List
  150. * @param list1 the first list, may be null
  151. * @param list2 the second list, may be null
  152. * @return whether the lists are equal by value comparison
  153. */
  154. public static boolean isEqualList(final Collection list1, final Collection list2) {
  155. if (list1 == list2) {
  156. return true;
  157. }
  158. if (list1 == null || list2 == null || list1.size() != list2.size()) {
  159. return false;
  160. }
  161. Iterator it1 = list1.iterator();
  162. Iterator it2 = list2.iterator();
  163. Object obj1 = null;
  164. Object obj2 = null;
  165. while (it1.hasNext() && it2.hasNext()) {
  166. obj1 = it1.next();
  167. obj2 = it2.next();
  168. if (!(obj1 == null ? obj2 == null : obj1.equals(obj2))) {
  169. return false;
  170. }
  171. }
  172. return !(it1.hasNext() || it2.hasNext());
  173. }
  174. /**
  175. * Generates a hash code using the algorithm specified in
  176. * {@link java.util.List#hashCode()}.
  177. * <p>
  178. * This method is useful for implementing <code>List</code> when you cannot
  179. * extend AbstractList. The method takes Collection instances to enable other
  180. * collection types to use the List implementation algorithm.
  181. *
  182. * @see java.util.List#hashCode()
  183. * @param list the list to generate the hashCode for, may be null
  184. * @return the hash code
  185. */
  186. public static int hashCodeForList(final Collection list) {
  187. if (list == null) {
  188. return 0;
  189. }
  190. int hashCode = 1;
  191. Iterator it = list.iterator();
  192. Object obj = null;
  193. while (it.hasNext()) {
  194. obj = it.next();
  195. hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
  196. }
  197. return hashCode;
  198. }
  199. //-----------------------------------------------------------------------
  200. /**
  201. * Returns a synchronized list backed by the given list.
  202. * <p>
  203. * You must manually synchronize on the returned buffer's iterator to
  204. * avoid non-deterministic behavior:
  205. *
  206. * <pre>
  207. * List list = ListUtils.synchronizedList(myList);
  208. * synchronized (list) {
  209. * Iterator i = list.iterator();
  210. * while (i.hasNext()) {
  211. * process (i.next());
  212. * }
  213. * }
  214. * </pre>
  215. *
  216. * This method uses the implementation in the decorators subpackage.
  217. *
  218. * @param list the list to synchronize, must not be null
  219. * @return a synchronized list backed by the given list
  220. * @throws IllegalArgumentException if the list is null
  221. */
  222. public static List synchronizedList(List list) {
  223. return SynchronizedList.decorate(list);
  224. }
  225. /**
  226. * Returns an unmodifiable list backed by the given list.
  227. * <p>
  228. * This method uses the implementation in the decorators subpackage.
  229. *
  230. * @param list the list to make unmodifiable, must not be null
  231. * @return an unmodifiable list backed by the given list
  232. * @throws IllegalArgumentException if the list is null
  233. */
  234. public static List unmodifiableList(List list) {
  235. return UnmodifiableList.decorate(list);
  236. }
  237. /**
  238. * Returns a predicated (validating) list backed by the given list.
  239. * <p>
  240. * Only objects that pass the test in the given predicate can be added to the list.
  241. * Trying to add an invalid object results in an IllegalArgumentException.
  242. * It is important not to use the original list after invoking this method,
  243. * as it is a backdoor for adding invalid objects.
  244. *
  245. * @param list the list to predicate, must not be null
  246. * @param predicate the predicate for the list, must not be null
  247. * @return a predicated list backed by the given list
  248. * @throws IllegalArgumentException if the List or Predicate is null
  249. */
  250. public static List predicatedList(List list, Predicate predicate) {
  251. return PredicatedList.decorate(list, predicate);
  252. }
  253. /**
  254. * Returns a typed list backed by the given list.
  255. * <p>
  256. * Only objects of the specified type can be added to the list.
  257. *
  258. * @param list the list to limit to a specific type, must not be null
  259. * @param type the type of objects which may be added to the list
  260. * @return a typed list backed by the specified list
  261. */
  262. public static List typedList(List list, Class type) {
  263. return TypedList.decorate(list, type);
  264. }
  265. /**
  266. * Returns a transformed list backed by the given list.
  267. * <p>
  268. * Each object is passed through the transformer as it is added to the
  269. * List. It is important not to use the original list after invoking this
  270. * method, as it is a backdoor for adding untransformed objects.
  271. *
  272. * @param list the list to predicate, must not be null
  273. * @param transformer the transformer for the list, must not be null
  274. * @return a transformed list backed by the given list
  275. * @throws IllegalArgumentException if the List or Transformer is null
  276. */
  277. public static List transformedList(List list, Transformer transformer) {
  278. return TransformedList.decorate(list, transformer);
  279. }
  280. /**
  281. * Returns a "lazy" list whose elements will be created on demand.
  282. * <p>
  283. * When the index passed to the returned list's {@link List#get(int) get}
  284. * method is greater than the list's size, then the factory will be used
  285. * to create a new object and that object will be inserted at that index.
  286. * <p>
  287. * For instance:
  288. *
  289. * <pre>
  290. * Factory factory = new Factory() {
  291. * public Object create() {
  292. * return new Date();
  293. * }
  294. * }
  295. * List lazy = ListUtils.lazyList(new ArrayList(), factory);
  296. * Object obj = lazy.get(3);
  297. * </pre>
  298. *
  299. * After the above code is executed, <code>obj</code> will contain
  300. * a new <code>Date</code> instance. Furthermore, that <code>Date</code>
  301. * instance is the fourth element in the list. The first, second,
  302. * and third element are all set to <code>null</code>.
  303. *
  304. * @param list the list to make lazy, must not be null
  305. * @param factory the factory for creating new objects, must not be null
  306. * @return a lazy list backed by the given list
  307. * @throws IllegalArgumentException if the List or Factory is null
  308. */
  309. public static List lazyList(List list, Factory factory) {
  310. return LazyList.decorate(list, factory);
  311. }
  312. /**
  313. * Returns a fixed-sized list backed by the given list.
  314. * Elements may not be added or removed from the returned list, but
  315. * existing elements can be changed (for instance, via the
  316. * {@link List#set(int,Object)} method).
  317. *
  318. * @param list the list whose size to fix, must not be null
  319. * @return a fixed-size list backed by that list
  320. * @throws IllegalArgumentException if the List is null
  321. */
  322. public static List fixedSizeList(List list) {
  323. return FixedSizeList.decorate(list);
  324. }
  325. }