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