View Javadoc
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  
19  import java.util.AbstractList;
20  import java.util.ArrayList;
21  import java.util.Collection;
22  import java.util.Collections;
23  import java.util.HashSet;
24  import java.util.Iterator;
25  import java.util.List;
26  import java.util.Objects;
27  
28  import org.apache.commons.collections4.bag.HashBag;
29  import org.apache.commons.collections4.functors.DefaultEquator;
30  import org.apache.commons.collections4.list.FixedSizeList;
31  import org.apache.commons.collections4.list.LazyList;
32  import org.apache.commons.collections4.list.PredicatedList;
33  import org.apache.commons.collections4.list.TransformedList;
34  import org.apache.commons.collections4.list.UnmodifiableList;
35  import org.apache.commons.collections4.sequence.CommandVisitor;
36  import org.apache.commons.collections4.sequence.EditScript;
37  import org.apache.commons.collections4.sequence.SequencesComparator;
38  
39  /**
40   * Provides utility methods and decorators for {@link List} instances.
41   *
42   * @since 1.0
43   */
44  public class ListUtils {
45  
46      /**
47       * A simple wrapper to use a CharSequence as List.
48       */
49      private static final class CharSequenceAsList extends AbstractList<Character> {
50          private final CharSequence sequence;
51  
52          CharSequenceAsList(final CharSequence sequence) {
53              this.sequence = sequence;
54          }
55  
56          @Override
57          public Character get(final int index) {
58              return Character.valueOf(sequence.charAt(index));
59          }
60  
61          @Override
62          public int size() {
63              return sequence.length();
64          }
65      }
66  
67      /**
68       * A helper class used to construct the longest common subsequence.
69       */
70      private static final class LcsVisitor<E> implements CommandVisitor<E> {
71          private final ArrayList<E> sequence;
72  
73          LcsVisitor() {
74              sequence = new ArrayList<>();
75          }
76  
77          public List<E> getSubSequence() {
78              return sequence;
79          }
80  
81          @Override
82          public void visitDeleteCommand(final E object) {
83              // noop
84          }
85  
86          @Override
87          public void visitInsertCommand(final E object) {
88              // noop
89          }
90  
91          @Override
92          public void visitKeepCommand(final E object) {
93              sequence.add(object);
94          }
95      }
96  
97      /**
98       * Provides a partition view on a {@link List}.
99       * @since 4.0
100      */
101     private static final class Partition<T> extends AbstractList<List<T>> {
102         private final List<T> list;
103         private final int size;
104 
105         private Partition(final List<T> list, final int size) {
106             this.list = list;
107             this.size = size;
108         }
109 
110         @Override
111         public List<T> get(final int index) {
112             final int listSize = size();
113             if (index < 0) {
114                 throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
115             }
116             if (index >= listSize) {
117                 throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
118                                                     listSize);
119             }
120             final int start = index * size;
121             final int end = Math.min(start + size, list.size());
122             return list.subList(start, end);
123         }
124 
125         @Override
126         public boolean isEmpty() {
127             return list.isEmpty();
128         }
129 
130         @Override
131         public int size() {
132             return (int) Math.ceil((double) list.size() / (double) size);
133         }
134     }
135 
136     /**
137      * Returns either the passed in list, or if the list is {@code null},
138      * the value of {@code defaultList}.
139      *
140      * @param <T> the element type
141      * @param list  the list, possibly {@code null}
142      * @param defaultList  the returned values if list is {@code null}
143      * @return an empty list if the argument is {@code null}
144      * @since 4.0
145      */
146     public static <T> List<T> defaultIfNull(final List<T> list, final List<T> defaultList) {
147         return list == null ? defaultList : list;
148     }
149 
150     /**
151      * Returns an immutable empty list if the argument is {@code null},
152      * or the argument itself otherwise.
153      *
154      * @param <T> the element type
155      * @param list the list, possibly {@code null}
156      * @return an empty list if the argument is {@code null}
157      */
158     public static <T> List<T> emptyIfNull(final List<T> list) {
159         return list == null ? Collections.<T>emptyList() : list;
160     }
161 
162     /**
163      * Returns a fixed-sized list backed by the given list.
164      * Elements may not be added or removed from the returned list, but
165      * existing elements can be changed (for instance, via the
166      * {@link List#set(int, Object)} method).
167      *
168      * @param <E>  the element type
169      * @param list  the list whose size to fix, must not be null
170      * @return a fixed-size list backed by that list
171      * @throws NullPointerException  if the List is null
172      */
173     public static <E> List<E> fixedSizeList(final List<E> list) {
174         return FixedSizeList.fixedSizeList(list);
175     }
176 
177     /**
178      * Gets the first element of a list.
179      * <p>
180      * Shorthand for {@code list.get(0)}
181      * </p>
182      *
183      * @param <T> The list type.
184      * @param list The list.
185      * @return the first element of a list.
186      * @see List#get(int)
187      * @since 4.5.0-M1
188      */
189     public static <T> T getFirst(final List<T> list) {
190         return Objects.requireNonNull(list, "list").get(0);
191     }
192 
193     /**
194      * Gets the last element of a list.
195      * <p>
196      * Shorthand for {@code list.get(list.size() - 1)}
197      * </p>
198      *
199      * @param <T> The list type.
200      * @param list The list.
201      * @return the last element of a list.
202      * @see List#get(int)
203      * @since 4.5.0-M1
204      */
205     public static <T> T getLast(final List<T> list) {
206         return Objects.requireNonNull(list, "list").get(list.size() - 1);
207     }
208 
209     /**
210      * Generates a hash code using the algorithm specified in
211      * {@link java.util.List#hashCode()}.
212      * <p>
213      * This method is useful for implementing {@code List} when you cannot
214      * extend AbstractList. The method takes Collection instances to enable other
215      * collection types to use the List implementation algorithm.
216      * </p>
217      *
218      * @see java.util.List#hashCode()
219      * @param list  the list to generate the hashCode for, may be null
220      * @return the hash code
221      */
222     public static int hashCodeForList(final Collection<?> list) {
223         if (list == null) {
224             return 0;
225         }
226         int hashCode = 1;
227 
228         for (final Object obj : list) {
229             hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
230         }
231         return hashCode;
232     }
233 
234     /**
235      * Finds the first index in the given List which matches the given predicate.
236      * <p>
237      * If the input List or predicate is null, or no element of the List
238      * matches the predicate, -1 is returned.
239      * </p>
240      *
241      * @param <E>  the element type
242      * @param list the List to search, may be null
243      * @param predicate  the predicate to use, may be null
244      * @return the first index of an Object in the List which matches the predicate or -1 if none could be found
245      */
246     public static <E> int indexOf(final List<E> list, final Predicate<E> predicate) {
247         if (list != null && predicate != null) {
248             for (int i = 0; i < list.size(); i++) {
249                 final E item = list.get(i);
250                 if (predicate.test(item)) {
251                     return i;
252                 }
253             }
254         }
255         return CollectionUtils.INDEX_NOT_FOUND;
256     }
257 
258     /**
259      * Returns a new list containing all elements that are contained in
260      * both given lists.
261      *
262      * @param <E> the element type
263      * @param list1  the first list
264      * @param list2  the second list
265      * @return  the intersection of those two lists
266      * @throws NullPointerException if either list is null
267      */
268     public static <E> List<E> intersection(final List<? extends E> list1, final List<? extends E> list2) {
269         final List<E> result = new ArrayList<>();
270 
271         List<? extends E> smaller = list1;
272         List<? extends E> larger = list2;
273         if (list1.size() > list2.size()) {
274             smaller = list2;
275             larger = list1;
276         }
277 
278         final HashSet<E> hashSet = new HashSet<>(smaller);
279 
280         for (final E e : larger) {
281             if (hashSet.contains(e)) {
282                 result.add(e);
283                 hashSet.remove(e);
284             }
285         }
286         return result;
287     }
288 
289     /**
290      * Tests two lists for value-equality as per the equality contract in
291      * {@link java.util.List#equals(Object)}.
292      * <p>
293      * This method is useful for implementing {@code List} when you cannot
294      * extend AbstractList. The method takes Collection instances to enable other
295      * collection types to use the List implementation algorithm.
296      * </p>
297      * <p>
298      * The relevant text (slightly paraphrased as this is a static method) is:
299      * </p>
300      * <blockquote>
301      * Compares the two list objects for equality.  Returns
302      * {@code true} if and only if both
303      * lists have the same size, and all corresponding pairs of elements in
304      * the two lists are <em>equal</em>.  (Two elements {@code e1} and
305      * {@code e2} are <em>equal</em> if {@code (e1==null ? e2==null :
306      * e1.equals(e2))}.)  In other words, two lists are defined to be
307      * equal if they contain the same elements in the same order.  This
308      * definition ensures that the equals method works properly across
309      * different implementations of the {@code List} interface.
310      * </blockquote>
311      * <p>
312      * <strong>Note:</strong> The behavior of this method is undefined if the lists are
313      * modified during the equals comparison.
314      * </p>
315      *
316      * @see java.util.List
317      * @param list1  the first list, may be null
318      * @param list2  the second list, may be null
319      * @return whether the lists are equal by value comparison
320      */
321     public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
322         if (list1 == list2) {
323             return true;
324         }
325         if (list1 == null || list2 == null || list1.size() != list2.size()) {
326             return false;
327         }
328 
329         final Iterator<?> it1 = list1.iterator();
330         final Iterator<?> it2 = list2.iterator();
331 
332         while (it1.hasNext() && it2.hasNext()) {
333             final Object obj1 = it1.next();
334             final Object obj2 = it2.next();
335 
336             if (!Objects.equals(obj1, obj2)) {
337                 return false;
338             }
339         }
340 
341         return !(it1.hasNext() || it2.hasNext());
342     }
343 
344     /**
345      * Returns a "lazy" list whose elements will be created on demand.
346      * <p>
347      * When the index passed to the returned list's {@link List#get(int) get}
348      * method is greater than the list's size, then the factory will be used
349      * to create a new object and that object will be inserted at that index.
350      * </p>
351      * <p>
352      * For instance:
353      * </p>
354      * <pre>
355      * Factory&lt;Date&gt; factory = new Factory&lt;Date&gt;() {
356      *     public Date create() {
357      *         return new Date();
358      *     }
359      * }
360      * List&lt;Date&gt; lazy = ListUtils.lazyList(new ArrayList&lt;Date&gt;(), factory);
361      * Date date = lazy.get(3);
362      * </pre>
363      * <p>
364      * After the above code is executed, {@code date} will refer to
365      * a new {@code Date} instance. Furthermore, that {@code Date}
366      * instance is the fourth element in the list.  The first, second,
367      * and third element are all set to {@code null}.
368      * </p>
369      *
370      * @param <E> the element type
371      * @param list  the list to make lazy, must not be null
372      * @param factory  the factory for creating new objects, must not be null
373      * @return a lazy list backed by the given list
374      * @throws NullPointerException if the List or Factory is null
375      */
376     public static <E> List<E> lazyList(final List<E> list, final Factory<? extends E> factory) {
377         return LazyList.lazyList(list, factory);
378     }
379 
380     /**
381      * Returns a "lazy" list whose elements will be created on demand.
382      * <p>
383      * When the index passed to the returned list's {@link List#get(int) get}
384      * method is greater than the list's size, then the transformer will be used
385      * to create a new object and that object will be inserted at that index.
386      * </p>
387      * <p>
388      * For instance:
389      * </p>
390      * <pre>
391      * List&lt;Integer&gt; hours = Arrays.asList(7, 5, 8, 2);
392      * Transformer&lt;Integer,Date&gt; transformer = input -&gt; LocalDateTime.now().withHour(hours.get(input));
393      * List&lt;LocalDateTime&gt; lazy = ListUtils.lazyList(new ArrayList&lt;LocalDateTime&gt;(), transformer);
394      * Date date = lazy.get(3);
395      * </pre>
396      * <p>
397      * After the above code is executed, {@code date} will refer to
398      * a new {@code Date} instance. Furthermore, that {@code Date}
399      * instance is the fourth element in the list.  The first, second,
400      * and third element are all set to {@code null}.
401      * </p>
402      *
403      * @param <E> the element type
404      * @param list  the list to make lazy, must not be null
405      * @param transformer  the transformer for creating new objects, must not be null
406      * @return a lazy list backed by the given list
407      * @throws NullPointerException if the List or Transformer is null
408      */
409     public static <E> List<E> lazyList(final List<E> list, final Transformer<Integer, ? extends E> transformer) {
410         return LazyList.lazyList(list, transformer);
411     }
412 
413     /**
414      * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects.
415      * <p>
416      * This is a convenience method for using {@link #longestCommonSubsequence(List, List)}
417      * with {@link CharSequence} instances.
418      * </p>
419      *
420      * @param charSequenceA  the first sequence
421      * @param charSequenceB  the second sequence
422      * @return the longest common subsequence as {@link String}
423      * @throws NullPointerException if either sequence is {@code null}
424      * @since 4.0
425      */
426     public static String longestCommonSubsequence(final CharSequence charSequenceA, final CharSequence charSequenceB) {
427         Objects.requireNonNull(charSequenceA, "charSequenceA");
428         Objects.requireNonNull(charSequenceB, "charSequenceB");
429         final List<Character> lcs = longestCommonSubsequence(new CharSequenceAsList(charSequenceA),
430                 new CharSequenceAsList(charSequenceB));
431         final StringBuilder sb = new StringBuilder();
432         for (final Character ch : lcs) {
433             sb.append(ch);
434         }
435         return sb.toString();
436     }
437 
438     /**
439      * Returns the longest common subsequence (LCS) of two sequences (lists).
440      *
441      * @param <E>  the element type
442      * @param a  the first list
443      * @param b  the second list
444      * @return the longest common subsequence
445      * @throws NullPointerException if either list is {@code null}
446      * @since 4.0
447      */
448     public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b) {
449         return longestCommonSubsequence(a, b, DefaultEquator.defaultEquator());
450     }
451 
452     /**
453      * Returns the longest common subsequence (LCS) of two sequences (lists).
454      *
455      * @param <E>  the element type
456      * @param listA  the first list
457      * @param listB  the second list
458      * @param equator  the equator used to test object equality
459      * @return the longest common subsequence
460      * @throws NullPointerException if either list or the equator is {@code null}
461      * @since 4.0
462      */
463     public static <E> List<E> longestCommonSubsequence(final List<E> listA, final List<E> listB,
464                                                        final Equator<? super E> equator) {
465         Objects.requireNonNull(listA, "listA");
466         Objects.requireNonNull(listB, "listB");
467         Objects.requireNonNull(equator, "equator");
468 
469         final SequencesComparator<E> comparator = new SequencesComparator<>(listA, listB, equator);
470         final EditScript<E> script = comparator.getScript();
471         final LcsVisitor<E> visitor = new LcsVisitor<>();
472         script.visit(visitor);
473         return visitor.getSubSequence();
474     }
475 
476     /**
477      * Returns consecutive {@link List#subList(int, int) sublists} of a
478      * list, each of the same size (the final list may be smaller). For example,
479      * partitioning a list containing {@code [a, b, c, d, e]} with a partition
480      * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
481      * two inner lists of three and two elements, all in the original order.
482      * <p>
483      * The outer list is unmodifiable, but reflects the latest state of the
484      * source list. The inner lists are sublist views of the original list,
485      * produced on demand using {@link List#subList(int, int)}, and are subject
486      * to all the usual caveats about modification as explained in that API.
487      * </p>
488      * <p>
489      * Adapted from https://github.com/google/guava
490      * </p>
491      *
492      * @param <T> the element type
493      * @param list  the list to return consecutive sublists of
494      * @param size  the desired size of each sublist (the last may be smaller)
495      * @return a list of consecutive sublists
496      * @throws NullPointerException if list is null
497      * @throws IllegalArgumentException if size is not strictly positive
498      * @since 4.0
499      */
500     public static <T> List<List<T>> partition(final List<T> list, final int size) {
501         Objects.requireNonNull(list, "list");
502         if (size <= 0) {
503             throw new IllegalArgumentException("Size must be greater than 0");
504         }
505         return new Partition<>(list, size);
506     }
507 
508     /**
509      * Returns a predicated (validating) list backed by the given list.
510      * <p>
511      * Only objects that pass the test in the given predicate can be added to the list.
512      * Trying to add an invalid object results in an IllegalArgumentException.
513      * It is important not to use the original list after invoking this method,
514      * as it is a backdoor for adding invalid objects.
515      * </p>
516      *
517      * @param <E> the element type
518      * @param list  the list to predicate, must not be null
519      * @param predicate  the predicate for the list, must not be null
520      * @return a predicated list backed by the given list
521      * @throws NullPointerException if the List or Predicate is null
522      */
523     public static <E> List<E> predicatedList(final List<E> list, final Predicate<E> predicate) {
524         return PredicatedList.predicatedList(list, predicate);
525     }
526 
527     /**
528      * Removes the elements in {@code remove} from {@code collection}. That is, this
529      * method returns a list containing all the elements in {@code collection}
530      * that are not in {@code remove}. The cardinality of an element {@code e}
531      * in the returned collection is the same as the cardinality of {@code e}
532      * in {@code collection} unless {@code remove} contains {@code e}, in which
533      * case the cardinality is zero. This method is useful if you do not wish to modify
534      * {@code collection} and thus cannot call {@code collection.removeAll(remove);}.
535      * <p>
536      * This implementation iterates over {@code collection}, checking each element in
537      * turn to see if it's contained in {@code remove}. If it's not contained, it's added
538      * to the returned list. As a consequence, it is advised to use a collection type for
539      * {@code remove} that provides a fast (e.g. O(1)) implementation of
540      * {@link Collection#contains(Object)}.
541      * </p>
542      *
543      * @param <E>  the element type
544      * @param collection  the collection from which items are removed (in the returned collection)
545      * @param remove  the items to be removed from the returned {@code collection}
546      * @return a {@code List} containing all the elements of {@code c} except
547      * any elements that also occur in {@code remove}.
548      * @throws NullPointerException if either parameter is null
549      * @since 3.2
550      */
551     public static <E> List<E> removeAll(final Collection<E> collection, final Collection<?> remove) {
552         Objects.requireNonNull(collection, "collection");
553         Objects.requireNonNull(remove, "remove");
554         final List<E> list = new ArrayList<>();
555         for (final E obj : collection) {
556             if (!remove.contains(obj)) {
557                 list.add(obj);
558             }
559         }
560         return list;
561     }
562 
563     /**
564      * Returns a List containing all the elements in {@code collection}
565      * that are also in {@code retain}. The cardinality of an element {@code e}
566      * in the returned list is the same as the cardinality of {@code e}
567      * in {@code collection} unless {@code retain} does not contain {@code e}, in which
568      * case the cardinality is zero. This method is useful if you do not wish to modify
569      * the collection {@code c} and thus cannot call {@code collection.retainAll(retain);}.
570      * <p>
571      * This implementation iterates over {@code collection}, checking each element in
572      * turn to see if it's contained in {@code retain}. If it's contained, it's added
573      * to the returned list. As a consequence, it is advised to use a collection type for
574      * {@code retain} that provides a fast (e.g. O(1)) implementation of
575      * {@link Collection#contains(Object)}.
576      * </p>
577      *
578      * @param <E>  the element type
579      * @param collection  the collection whose contents are the target of the #retailAll operation
580      * @param retain  the collection containing the elements to be retained in the returned collection
581      * @return a {@code List} containing all the elements of {@code c}
582      * that occur at least once in {@code retain}.
583      * @throws NullPointerException if either parameter is null
584      * @since 3.2
585      */
586     public static <E> List<E> retainAll(final Collection<E> collection, final Collection<?> retain) {
587         final List<E> list = new ArrayList<>(Math.min(collection.size(), retain.size()));
588 
589         for (final E obj : collection) {
590             if (retain.contains(obj)) {
591                 list.add(obj);
592             }
593         }
594         return list;
595     }
596 
597     /**
598      * Selects all elements from input collection which match the given
599      * predicate into an output list.
600      * <p>
601      * A {@code null} predicate matches no elements.
602      * </p>
603      *
604      * @param <E> the element type
605      * @param inputCollection  the collection to get the input from, may not be null
606      * @param predicate  the predicate to use, may be null
607      * @return the elements matching the predicate (new list)
608      * @throws NullPointerException if the input list is null
609      * @since 4.0
610      * @see CollectionUtils#select(Iterable, Predicate)
611      */
612     public static <E> List<E> select(final Collection<? extends E> inputCollection,
613             final Predicate<? super E> predicate) {
614         return CollectionUtils.select(inputCollection, predicate, new ArrayList<>(inputCollection.size()));
615     }
616 
617     /**
618      * Selects all elements from inputCollection which don't match the given
619      * predicate into an output collection.
620      * <p>
621      * If the input predicate is {@code null}, the result is an empty list.
622      * </p>
623      *
624      * @param <E> the element type
625      * @param inputCollection the collection to get the input from, may not be null
626      * @param predicate the predicate to use, may be null
627      * @return the elements <strong>not</strong> matching the predicate (new list)
628      * @throws NullPointerException if the input collection is null
629      * @since 4.0
630      * @see CollectionUtils#selectRejected(Iterable, Predicate)
631      */
632     public static <E> List<E> selectRejected(final Collection<? extends E> inputCollection,
633             final Predicate<? super E> predicate) {
634         return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList<>(inputCollection.size()));
635     }
636 
637     /**
638      * Subtracts all elements in the second list from the first list,
639      * placing the results in a new list.
640      * <p>
641      * This differs from {@link List#removeAll(Collection)} in that
642      * cardinality is respected; if <Code>list1</Code> contains two
643      * occurrences of <Code>null</Code> and <Code>list2</Code> only
644      * contains one occurrence, then the returned list will still contain
645      * one occurrence.
646      * </p>
647      *
648      * @param <E> the element type
649      * @param list1  the list to subtract from
650      * @param list2  the list to subtract
651      * @return a new list containing the results
652      * @throws NullPointerException if either list is null
653      */
654     public static <E> List<E> subtract(final List<E> list1, final List<? extends E> list2) {
655         final ArrayList<E> result = new ArrayList<>();
656         final HashBag<E> bag = new HashBag<>(list2);
657         for (final E e : list1) {
658             if (!bag.remove(e, 1)) {
659                 result.add(e);
660             }
661         }
662         return result;
663     }
664 
665     /**
666      * Returns the sum of the given lists.  This is their intersection
667      * subtracted from their union.
668      *
669      * @param <E> the element type
670      * @param list1  the first list
671      * @param list2  the second list
672      * @return  a new list containing the sum of those lists
673      * @throws NullPointerException if either list is null
674      */
675     public static <E> List<E> sum(final List<? extends E> list1, final List<? extends E> list2) {
676         return subtract(union(list1, list2), intersection(list1, list2));
677     }
678 
679     /**
680      * Returns a synchronized list backed by the given list.
681      * <p>
682      * You must manually synchronize on the returned list's iterator to
683      * avoid non-deterministic behavior:
684      * </p>
685      * <pre>
686      * List list = ListUtils.synchronizedList(myList);
687      * synchronized (list) {
688      *     Iterator i = list.iterator();
689      *     while (i.hasNext()) {
690      *         process (i.next());
691      *     }
692      * }
693      * </pre>
694      * <p>
695      * This method is just a wrapper for {@link Collections#synchronizedList(List)}.
696      * </p>
697      *
698      * @param <E> the element type
699      * @param list  the list to synchronize, must not be null
700      * @return a synchronized list backed by the given list
701      * @throws NullPointerException if the list is null
702      */
703     public static <E> List<E> synchronizedList(final List<E> list) {
704         return Collections.synchronizedList(list);
705     }
706 
707     /**
708      * Returns a transformed list backed by the given list.
709      * <p>
710      * This method returns a new list (decorating the specified list) that
711      * will transform any new entries added to it.
712      * Existing entries in the specified list will not be transformed.
713      * </p>
714      * <p>
715      * Each object is passed through the transformer as it is added to the
716      * List. It is important not to use the original list after invoking this
717      * method, as it is a backdoor for adding untransformed objects.
718      * </p>
719      * <p>
720      * Existing entries in the specified list will not be transformed.
721      * If you want that behavior, see {@link TransformedList#transformedList}.
722      * </p>
723      *
724      * @param <E> the element type
725      * @param list  the list to predicate, must not be null
726      * @param transformer  the transformer for the list, must not be null
727      * @return a transformed list backed by the given list
728      * @throws NullPointerException if the List or Transformer is null
729      */
730     public static <E> List<E> transformedList(final List<E> list,
731                                               final Transformer<? super E, ? extends E> transformer) {
732         return TransformedList.transformingList(list, transformer);
733     }
734 
735     /**
736      * Returns a new list containing the second list appended to the
737      * first list.  The {@link List#addAll(Collection)} operation is
738      * used to append the two given lists into a new list.
739      *
740      * @param <E> the element type
741      * @param list1  the first list
742      * @param list2  the second list
743      * @return a new list containing the union of those lists
744      * @throws NullPointerException if either list is null
745      */
746     public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) {
747         final ArrayList<E> result = new ArrayList<>(list1.size() + list2.size());
748         result.addAll(list1);
749         result.addAll(list2);
750         return result;
751     }
752 
753     /**
754      * Returns an unmodifiable list backed by the given list.
755      * <p>
756      * This method uses the implementation in the decorators subpackage.
757      * </p>
758      *
759      * @param <E>  the element type
760      * @param list  the list to make unmodifiable, must not be null
761      * @return an unmodifiable list backed by the given list
762      * @throws NullPointerException if the list is null
763      */
764     public static <E> List<E> unmodifiableList(final List<? extends E> list) {
765         return UnmodifiableList.unmodifiableList(list);
766     }
767 
768     /**
769      * Don't allow instances.
770      */
771     private ListUtils() {
772         // empty
773     }
774 
775 }