001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      http://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.collections4;
018
019import java.util.AbstractList;
020import java.util.ArrayList;
021import java.util.Collection;
022import java.util.Collections;
023import java.util.HashSet;
024import java.util.Iterator;
025import java.util.List;
026import java.util.Objects;
027
028import org.apache.commons.collections4.bag.HashBag;
029import org.apache.commons.collections4.functors.DefaultEquator;
030import org.apache.commons.collections4.list.FixedSizeList;
031import org.apache.commons.collections4.list.LazyList;
032import org.apache.commons.collections4.list.PredicatedList;
033import org.apache.commons.collections4.list.TransformedList;
034import org.apache.commons.collections4.list.UnmodifiableList;
035import org.apache.commons.collections4.sequence.CommandVisitor;
036import org.apache.commons.collections4.sequence.EditScript;
037import org.apache.commons.collections4.sequence.SequencesComparator;
038
039/**
040 * Provides utility methods and decorators for {@link List} instances.
041 *
042 * @since 1.0
043 */
044public class ListUtils {
045    /**
046     * A simple wrapper to use a CharSequence as List.
047     */
048    private static final class CharSequenceAsList extends AbstractList<Character> {
049        private final CharSequence sequence;
050
051        CharSequenceAsList(final CharSequence sequence) {
052            this.sequence = sequence;
053        }
054
055        @Override
056        public Character get(final int index) {
057            return Character.valueOf(sequence.charAt(index));
058        }
059
060        @Override
061        public int size() {
062            return sequence.length();
063        }
064    }
065
066    /**
067     * A helper class used to construct the longest common subsequence.
068     */
069    private static final class LcsVisitor<E> implements CommandVisitor<E> {
070        private final ArrayList<E> sequence;
071
072        LcsVisitor() {
073            sequence = new ArrayList<>();
074        }
075
076        public List<E> getSubSequence() {
077            return sequence;
078        }
079
080        @Override
081        public void visitDeleteCommand(final E object) {
082            // noop
083        }
084
085        @Override
086        public void visitInsertCommand(final E object) {
087            // noop
088        }
089
090        @Override
091        public void visitKeepCommand(final E object) {
092            sequence.add(object);
093        }
094    }
095
096    /**
097     * Provides a partition view on a {@link List}.
098     * @since 4.0
099     */
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}