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