    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}