You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/08/02 17:41:25 UTC

[commons-collections] branch master updated (fc99d09 -> bfede0e)

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git.


    from fc99d09  Update tests from commons-io:commons-io 2.10.0 to 2.11.0.
     new 90d2a9b  Sort members.
     new 09d8151  Sort by type.
     new bfede0e  Add ListUtils.getFirst() and getLast().

The 3 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/changes/changes.xml                            |  116 +--
 .../org/apache/commons/collections4/ListUtils.java | 1006 ++++++++++----------
 .../apache/commons/collections4/ListUtilsTest.java |  404 ++++----
 3 files changed, 788 insertions(+), 738 deletions(-)

[commons-collections] 01/03: Sort members.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit 90d2a9bcee6768e0c18ed1b9913c70aef8ff12d6
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Aug 2 13:23:50 2021 -0400

    Sort members.
---
 .../org/apache/commons/collections4/ListUtils.java | 948 ++++++++++-----------
 .../apache/commons/collections4/ListUtilsTest.java | 390 ++++-----
 2 files changed, 669 insertions(+), 669 deletions(-)

diff --git a/src/main/java/org/apache/commons/collections4/ListUtils.java b/src/main/java/org/apache/commons/collections4/ListUtils.java
index 548bf14..e8c3d8a 100644
--- a/src/main/java/org/apache/commons/collections4/ListUtils.java
+++ b/src/main/java/org/apache/commons/collections4/ListUtils.java
@@ -43,21 +43,94 @@ import org.apache.commons.collections4.sequence.SequencesComparator;
  */
 public class ListUtils {
     /**
-     * Don't allow instances.
+     * A simple wrapper to use a CharSequence as List.
      */
-    private ListUtils() {}
+    private static final class CharSequenceAsList extends AbstractList<Character> {
+        private final CharSequence sequence;
+
+        CharSequenceAsList(final CharSequence sequence) {
+            this.sequence = sequence;
+        }
+
+        @Override
+        public Character get(final int index) {
+            return Character.valueOf(sequence.charAt(index));
+        }
+
+        @Override
+        public int size() {
+            return sequence.length();
+        }
+    }
 
 
     /**
-     * Returns an immutable empty list if the argument is {@code null},
-     * or the argument itself otherwise.
-     *
-     * @param <T> the element type
-     * @param list the list, possibly {@code null}
-     * @return an empty list if the argument is {@code null}
+     * A helper class used to construct the longest common subsequence.
      */
-    public static <T> List<T> emptyIfNull(final List<T> list) {
-        return list == null ? Collections.<T>emptyList() : list;
+    private static final class LcsVisitor<E> implements CommandVisitor<E> {
+        private final ArrayList<E> sequence;
+
+        LcsVisitor() {
+            sequence = new ArrayList<>();
+        }
+
+        public List<E> getSubSequence() {
+            return sequence;
+        }
+
+        @Override
+        public void visitDeleteCommand(final E object) {
+            // noop
+        }
+
+        @Override
+        public void visitInsertCommand(final E object) {
+            // noop
+        }
+
+        @Override
+        public void visitKeepCommand(final E object) {
+            sequence.add(object);
+        }
+    }
+
+    /**
+     * Provides a partition view on a {@link List}.
+     * @since 4.0
+     */
+    private static class Partition<T> extends AbstractList<List<T>> {
+        private final List<T> list;
+        private final int size;
+
+        private Partition(final List<T> list, final int size) {
+            this.list = list;
+            this.size = size;
+        }
+
+        @Override
+        public List<T> get(final int index) {
+            final int listSize = size();
+            if (index < 0) {
+                throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
+            }
+            if (index >= listSize) {
+                throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
+                                                    listSize);
+            }
+            final int start = index * size;
+            final int end = Math.min(start + size, list.size());
+            return list.subList(start, end);
+        }
+
+        @Override
+        public boolean isEmpty() {
+            return list.isEmpty();
+        }
+
+        @Override
+        public int size() {
+            return (int) Math.ceil((double) list.size() / (double) size);
+        }
     }
 
     /**
@@ -75,6 +148,82 @@ public class ListUtils {
     }
 
     /**
+     * Returns an immutable empty list if the argument is {@code null},
+     * or the argument itself otherwise.
+     *
+     * @param <T> the element type
+     * @param list the list, possibly {@code null}
+     * @return an empty list if the argument is {@code null}
+     */
+    public static <T> List<T> emptyIfNull(final List<T> list) {
+        return list == null ? Collections.<T>emptyList() : list;
+    }
+
+    /**
+     * Returns a fixed-sized list backed by the given list.
+     * Elements may not be added or removed from the returned list, but
+     * existing elements can be changed (for instance, via the
+     * {@link List#set(int, Object)} method).
+     *
+     * @param <E>  the element type
+     * @param list  the list whose size to fix, must not be null
+     * @return a fixed-size list backed by that list
+     * @throws NullPointerException  if the List is null
+     */
+    public static <E> List<E> fixedSizeList(final List<E> list) {
+        return FixedSizeList.fixedSizeList(list);
+    }
+
+    /**
+     * Generates a hash code using the algorithm specified in
+     * {@link java.util.List#hashCode()}.
+     * <p>
+     * This method is useful for implementing {@code List} when you cannot
+     * extend AbstractList. The method takes Collection instances to enable other
+     * collection types to use the List implementation algorithm.
+     *
+     * @see java.util.List#hashCode()
+     * @param list  the list to generate the hashCode for, may be null
+     * @return the hash code
+     */
+    public static int hashCodeForList(final Collection<?> list) {
+        if (list == null) {
+            return 0;
+        }
+        int hashCode = 1;
+        final Iterator<?> it = list.iterator();
+
+        while (it.hasNext()) {
+            final Object obj = it.next();
+            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+        }
+        return hashCode;
+    }
+
+    /**
+     * Finds the first index in the given List which matches the given predicate.
+     * <p>
+     * If the input List or predicate is null, or no element of the List
+     * matches the predicate, -1 is returned.
+     *
+     * @param <E>  the element type
+     * @param list the List to search, may be null
+     * @param predicate  the predicate to use, may be null
+     * @return the first index of an Object in the List which matches the predicate or -1 if none could be found
+     */
+    public static <E> int indexOf(final List<E> list, final Predicate<E> predicate) {
+        if (list != null && predicate != null) {
+            for (int i = 0; i < list.size(); i++) {
+                final E item = list.get(i);
+                if (predicate.evaluate(item)) {
+                    return i;
+                }
+            }
+        }
+        return CollectionUtils.INDEX_NOT_FOUND;
+    }
+
+    /**
      * Returns a new list containing all elements that are contained in
      * both given lists.
      *
@@ -106,215 +255,232 @@ public class ListUtils {
     }
 
     /**
-     * Subtracts all elements in the second list from the first list,
-     * placing the results in a new list.
+     * Tests two lists for value-equality as per the equality contract in
+     * {@link java.util.List#equals(java.lang.Object)}.
      * <p>
-     * This differs from {@link List#removeAll(Collection)} in that
-     * cardinality is respected; if <Code>list1</Code> contains two
-     * occurrences of <Code>null</Code> and <Code>list2</Code> only
-     * contains one occurrence, then the returned list will still contain
-     * one occurrence.
+     * This method is useful for implementing {@code List} when you cannot
+     * extend AbstractList. The method takes Collection instances to enable other
+     * collection types to use the List implementation algorithm.
+     * <p>
+     * The relevant text (slightly paraphrased as this is a static method) is:
+     * <blockquote>
+     * Compares the two list objects for equality.  Returns
+     * {@code true} if and only if both
+     * lists have the same size, and all corresponding pairs of elements in
+     * the two lists are <i>equal</i>.  (Two elements {@code e1} and
+     * {@code e2} are <i>equal</i> if <code>(e1==null ? e2==null :
+     * e1.equals(e2))</code>.)  In other words, two lists are defined to be
+     * equal if they contain the same elements in the same order.  This
+     * definition ensures that the equals method works properly across
+     * different implementations of the {@code List} interface.
+     * </blockquote>
      *
-     * @param <E> the element type
-     * @param list1  the list to subtract from
-     * @param list2  the list to subtract
-     * @return a new list containing the results
-     * @throws NullPointerException if either list is null
+     * <b>Note:</b> The behavior of this method is undefined if the lists are
+     * modified during the equals comparison.
+     *
+     * @see java.util.List
+     * @param list1  the first list, may be null
+     * @param list2  the second list, may be null
+     * @return whether the lists are equal by value comparison
      */
-    public static <E> List<E> subtract(final List<E> list1, final List<? extends E> list2) {
-        final ArrayList<E> result = new ArrayList<>();
-        final HashBag<E> bag = new HashBag<>(list2);
-        for (final E e : list1) {
-            if (!bag.remove(e, 1)) {
-                result.add(e);
+    public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
+        if (list1 == list2) {
+            return true;
+        }
+        if (list1 == null || list2 == null || list1.size() != list2.size()) {
+            return false;
+        }
+
+        final Iterator<?> it1 = list1.iterator();
+        final Iterator<?> it2 = list2.iterator();
+        Object obj1 = null;
+        Object obj2 = null;
+
+        while (it1.hasNext() && it2.hasNext()) {
+            obj1 = it1.next();
+            obj2 = it2.next();
+
+            if (!(obj1 == null ? obj2 == null : obj1.equals(obj2))) {
+                return false;
             }
         }
-        return result;
-    }
 
-    /**
-     * Returns the sum of the given lists.  This is their intersection
-     * subtracted from their union.
-     *
-     * @param <E> the element type
-     * @param list1  the first list
-     * @param list2  the second list
-     * @return  a new list containing the sum of those lists
-     * @throws NullPointerException if either list is null
-     */
-    public static <E> List<E> sum(final List<? extends E> list1, final List<? extends E> list2) {
-        return subtract(union(list1, list2), intersection(list1, list2));
+        return !(it1.hasNext() || it2.hasNext());
     }
 
     /**
-     * Returns a new list containing the second list appended to the
-     * first list.  The {@link List#addAll(Collection)} operation is
-     * used to append the two given lists into a new list.
+     * Returns a "lazy" list whose elements will be created on demand.
+     * <p>
+     * When the index passed to the returned list's {@link List#get(int) get}
+     * method is greater than the list's size, then the factory will be used
+     * to create a new object and that object will be inserted at that index.
+     * <p>
+     * For instance:
+     *
+     * <pre>
+     * Factory&lt;Date&gt; factory = new Factory&lt;Date&gt;() {
+     *     public Date create() {
+     *         return new Date();
+     *     }
+     * }
+     * List&lt;Date&gt; lazy = ListUtils.lazyList(new ArrayList&lt;Date&gt;(), factory);
+     * Date date = lazy.get(3);
+     * </pre>
+     *
+     * After the above code is executed, {@code date} will refer to
+     * a new {@code Date} instance. Furthermore, that {@code Date}
+     * instance is the fourth element in the list.  The first, second,
+     * and third element are all set to {@code null}.
      *
      * @param <E> the element type
-     * @param list1  the first list
-     * @param list2  the second list
-     * @return a new list containing the union of those lists
-     * @throws NullPointerException if either list is null
+     * @param list  the list to make lazy, must not be null
+     * @param factory  the factory for creating new objects, must not be null
+     * @return a lazy list backed by the given list
+     * @throws NullPointerException if the List or Factory is null
      */
-    public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) {
-        final ArrayList<E> result = new ArrayList<>(list1.size() + list2.size());
-        result.addAll(list1);
-        result.addAll(list2);
-        return result;
+    public static <E> List<E> lazyList(final List<E> list, final Factory<? extends E> factory) {
+        return LazyList.lazyList(list, factory);
     }
 
     /**
-     * Selects all elements from input collection which match the given
-     * predicate into an output list.
+     * Returns a "lazy" list whose elements will be created on demand.
      * <p>
-     * A {@code null} predicate matches no elements.
+     * When the index passed to the returned list's {@link List#get(int) get}
+     * method is greater than the list's size, then the transformer will be used
+     * to create a new object and that object will be inserted at that index.
+     * <p>
+     * For instance:
      *
-     * @param <E> the element type
-     * @param inputCollection  the collection to get the input from, may not be null
-     * @param predicate  the predicate to use, may be null
-     * @return the elements matching the predicate (new list)
-     * @throws NullPointerException if the input list is null
+     * <pre>
+     * List&lt;Integer&gt; hours = Arrays.asList(7, 5, 8, 2);
+     * Transformer&lt;Integer,Date&gt; transformer = input -&gt; LocalDateTime.now().withHour(hours.get(input));
+     * List&lt;LocalDateTime&gt; lazy = ListUtils.lazyList(new ArrayList&lt;LocalDateTime&gt;(), transformer);
+     * Date date = lazy.get(3);
+     * </pre>
      *
-     * @since 4.0
-     * @see CollectionUtils#select(Iterable, Predicate)
+     * After the above code is executed, {@code date} will refer to
+     * a new {@code Date} instance. Furthermore, that {@code Date}
+     * instance is the fourth element in the list.  The first, second,
+     * and third element are all set to {@code null}.
+     *
+     * @param <E> the element type
+     * @param list  the list to make lazy, must not be null
+     * @param transformer  the transformer for creating new objects, must not be null
+     * @return a lazy list backed by the given list
+     * @throws NullPointerException if the List or Transformer is null
      */
-    public static <E> List<E> select(final Collection<? extends E> inputCollection,
-            final Predicate<? super E> predicate) {
-        return CollectionUtils.select(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
+    public static <E> List<E> lazyList(final List<E> list, final Transformer<Integer, ? extends E> transformer) {
+        return LazyList.lazyList(list, transformer);
     }
 
     /**
-     * Selects all elements from inputCollection which don't match the given
-     * predicate into an output collection.
+     * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects.
      * <p>
-     * If the input predicate is {@code null}, the result is an empty list.
-     *
-     * @param <E> the element type
-     * @param inputCollection the collection to get the input from, may not be null
-     * @param predicate the predicate to use, may be null
-     * @return the elements <b>not</b> matching the predicate (new list)
-     * @throws NullPointerException if the input collection is null
+     * This is a convenience method for using {@link #longestCommonSubsequence(List, List)}
+     * with {@link CharSequence} instances.
      *
+     * @param charSequenceA  the first sequence
+     * @param charSequenceB  the second sequence
+     * @return the longest common subsequence as {@link String}
+     * @throws NullPointerException if either sequence is {@code null}
      * @since 4.0
-     * @see CollectionUtils#selectRejected(Iterable, Predicate)
      */
-    public static <E> List<E> selectRejected(final Collection<? extends E> inputCollection,
-            final Predicate<? super E> predicate) {
-        return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
+    public static String longestCommonSubsequence(final CharSequence charSequenceA, final CharSequence charSequenceB) {
+        Objects.requireNonNull(charSequenceA, "charSequenceA");
+        Objects.requireNonNull(charSequenceB, "charSequenceB");
+        final List<Character> lcs = longestCommonSubsequence(new CharSequenceAsList(charSequenceA),
+                new CharSequenceAsList(charSequenceB));
+        final StringBuilder sb = new StringBuilder();
+        for (final Character ch : lcs) {
+            sb.append(ch);
+        }
+        return sb.toString();
     }
 
     /**
-     * Tests two lists for value-equality as per the equality contract in
-     * {@link java.util.List#equals(java.lang.Object)}.
-     * <p>
-     * This method is useful for implementing {@code List} when you cannot
-     * extend AbstractList. The method takes Collection instances to enable other
-     * collection types to use the List implementation algorithm.
-     * <p>
-     * The relevant text (slightly paraphrased as this is a static method) is:
-     * <blockquote>
-     * Compares the two list objects for equality.  Returns
-     * {@code true} if and only if both
-     * lists have the same size, and all corresponding pairs of elements in
-     * the two lists are <i>equal</i>.  (Two elements {@code e1} and
-     * {@code e2} are <i>equal</i> if <code>(e1==null ? e2==null :
-     * e1.equals(e2))</code>.)  In other words, two lists are defined to be
-     * equal if they contain the same elements in the same order.  This
-     * definition ensures that the equals method works properly across
-     * different implementations of the {@code List} interface.
-     * </blockquote>
-     *
-     * <b>Note:</b> The behavior of this method is undefined if the lists are
-     * modified during the equals comparison.
+     * Returns the longest common subsequence (LCS) of two sequences (lists).
      *
-     * @see java.util.List
-     * @param list1  the first list, may be null
-     * @param list2  the second list, may be null
-     * @return whether the lists are equal by value comparison
+     * @param <E>  the element type
+     * @param a  the first list
+     * @param b  the second list
+     * @return the longest common subsequence
+     * @throws NullPointerException if either list is {@code null}
+     * @since 4.0
      */
-    public static boolean isEqualList(final Collection<?> list1, final Collection<?> list2) {
-        if (list1 == list2) {
-            return true;
-        }
-        if (list1 == null || list2 == null || list1.size() != list2.size()) {
-            return false;
-        }
-
-        final Iterator<?> it1 = list1.iterator();
-        final Iterator<?> it2 = list2.iterator();
-        Object obj1 = null;
-        Object obj2 = null;
-
-        while (it1.hasNext() && it2.hasNext()) {
-            obj1 = it1.next();
-            obj2 = it2.next();
+    public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b) {
+        return longestCommonSubsequence( a, b, DefaultEquator.defaultEquator() );
+    }
 
-            if (!(obj1 == null ? obj2 == null : obj1.equals(obj2))) {
-                return false;
-            }
-        }
+    /**
+     * Returns the longest common subsequence (LCS) of two sequences (lists).
+     *
+     * @param <E>  the element type
+     * @param listA  the first list
+     * @param listB  the second list
+     * @param equator  the equator used to test object equality
+     * @return the longest common subsequence
+     * @throws NullPointerException if either list or the equator is {@code null}
+     * @since 4.0
+     */
+    public static <E> List<E> longestCommonSubsequence(final List<E> listA, final List<E> listB,
+                                                       final Equator<? super E> equator) {
+        Objects.requireNonNull(listA, "listA");
+        Objects.requireNonNull(listB, "listB");
+        Objects.requireNonNull(equator, "equator");
 
-        return !(it1.hasNext() || it2.hasNext());
+        final SequencesComparator<E> comparator = new SequencesComparator<>(listA, listB, equator);
+        final EditScript<E> script = comparator.getScript();
+        final LcsVisitor<E> visitor = new LcsVisitor<>();
+        script.visit(visitor);
+        return visitor.getSubSequence();
     }
 
     /**
-     * Generates a hash code using the algorithm specified in
-     * {@link java.util.List#hashCode()}.
+     * Returns consecutive {@link List#subList(int, int) sublists} of a
+     * list, each of the same size (the final list may be smaller). For example,
+     * partitioning a list containing {@code [a, b, c, d, e]} with a partition
+     * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
+     * two inner lists of three and two elements, all in the original order.
      * <p>
-     * This method is useful for implementing {@code List} when you cannot
-     * extend AbstractList. The method takes Collection instances to enable other
-     * collection types to use the List implementation algorithm.
+     * The outer list is unmodifiable, but reflects the latest state of the
+     * source list. The inner lists are sublist views of the original list,
+     * produced on demand using {@link List#subList(int, int)}, and are subject
+     * to all the usual caveats about modification as explained in that API.
+     * <p>
+     * Adapted from http://code.google.com/p/guava-libraries/
      *
-     * @see java.util.List#hashCode()
-     * @param list  the list to generate the hashCode for, may be null
-     * @return the hash code
+     * @param <T> the element type
+     * @param list  the list to return consecutive sublists of
+     * @param size  the desired size of each sublist (the last may be smaller)
+     * @return a list of consecutive sublists
+     * @throws NullPointerException if list is null
+     * @throws IllegalArgumentException if size is not strictly positive
+     * @since 4.0
      */
-    public static int hashCodeForList(final Collection<?> list) {
-        if (list == null) {
-            return 0;
-        }
-        int hashCode = 1;
-        final Iterator<?> it = list.iterator();
-
-        while (it.hasNext()) {
-            final Object obj = it.next();
-            hashCode = 31 * hashCode + (obj == null ? 0 : obj.hashCode());
+    public static <T> List<List<T>> partition(final List<T> list, final int size) {
+        Objects.requireNonNull(list, "list");
+        if (size <= 0) {
+            throw new IllegalArgumentException("Size must be greater than 0");
         }
-        return hashCode;
+        return new Partition<>(list, size);
     }
 
     /**
-     * Returns a List containing all the elements in {@code collection}
-     * that are also in {@code retain}. The cardinality of an element {@code e}
-     * in the returned list is the same as the cardinality of {@code e}
-     * in {@code collection} unless {@code retain} does not contain {@code e}, in which
-     * case the cardinality is zero. This method is useful if you do not wish to modify
-     * the collection {@code c} and thus cannot call {@code collection.retainAll(retain);}.
+     * Returns a predicated (validating) list backed by the given list.
      * <p>
-     * This implementation iterates over {@code collection}, checking each element in
-     * turn to see if it's contained in {@code retain}. If it's contained, it's added
-     * to the returned list. As a consequence, it is advised to use a collection type for
-     * {@code retain} that provides a fast (e.g. O(1)) implementation of
-     * {@link Collection#contains(Object)}.
+     * Only objects that pass the test in the given predicate can be added to the list.
+     * Trying to add an invalid object results in an IllegalArgumentException.
+     * It is important not to use the original list after invoking this method,
+     * as it is a backdoor for adding invalid objects.
      *
-     * @param <E>  the element type
-     * @param collection  the collection whose contents are the target of the #retailAll operation
-     * @param retain  the collection containing the elements to be retained in the returned collection
-     * @return a {@code List} containing all the elements of {@code c}
-     * that occur at least once in {@code retain}.
-     * @throws NullPointerException if either parameter is null
-     * @since 3.2
+     * @param <E> the element type
+     * @param list  the list to predicate, must not be null
+     * @param predicate  the predicate for the list, must not be null
+     * @return a predicated list backed by the given list
+     * @throws NullPointerException if the List or Predicate is null
      */
-    public static <E> List<E> retainAll(final Collection<E> collection, final Collection<?> retain) {
-        final List<E> list = new ArrayList<>(Math.min(collection.size(), retain.size()));
-
-        for (final E obj : collection) {
-            if (retain.contains(obj)) {
-                list.add(obj);
-            }
-        }
-        return list;
+    public static <E> List<E> predicatedList(final List<E> list, final Predicate<E> predicate) {
+        return PredicatedList.predicatedList(list, predicate);
     }
 
     /**
@@ -351,6 +517,120 @@ public class ListUtils {
     }
 
     /**
+     * Returns a List containing all the elements in {@code collection}
+     * that are also in {@code retain}. The cardinality of an element {@code e}
+     * in the returned list is the same as the cardinality of {@code e}
+     * in {@code collection} unless {@code retain} does not contain {@code e}, in which
+     * case the cardinality is zero. This method is useful if you do not wish to modify
+     * the collection {@code c} and thus cannot call {@code collection.retainAll(retain);}.
+     * <p>
+     * This implementation iterates over {@code collection}, checking each element in
+     * turn to see if it's contained in {@code retain}. If it's contained, it's added
+     * to the returned list. As a consequence, it is advised to use a collection type for
+     * {@code retain} that provides a fast (e.g. O(1)) implementation of
+     * {@link Collection#contains(Object)}.
+     *
+     * @param <E>  the element type
+     * @param collection  the collection whose contents are the target of the #retailAll operation
+     * @param retain  the collection containing the elements to be retained in the returned collection
+     * @return a {@code List} containing all the elements of {@code c}
+     * that occur at least once in {@code retain}.
+     * @throws NullPointerException if either parameter is null
+     * @since 3.2
+     */
+    public static <E> List<E> retainAll(final Collection<E> collection, final Collection<?> retain) {
+        final List<E> list = new ArrayList<>(Math.min(collection.size(), retain.size()));
+
+        for (final E obj : collection) {
+            if (retain.contains(obj)) {
+                list.add(obj);
+            }
+        }
+        return list;
+    }
+
+    /**
+     * Selects all elements from input collection which match the given
+     * predicate into an output list.
+     * <p>
+     * A {@code null} predicate matches no elements.
+     *
+     * @param <E> the element type
+     * @param inputCollection  the collection to get the input from, may not be null
+     * @param predicate  the predicate to use, may be null
+     * @return the elements matching the predicate (new list)
+     * @throws NullPointerException if the input list is null
+     *
+     * @since 4.0
+     * @see CollectionUtils#select(Iterable, Predicate)
+     */
+    public static <E> List<E> select(final Collection<? extends E> inputCollection,
+            final Predicate<? super E> predicate) {
+        return CollectionUtils.select(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
+    }
+
+    /**
+     * Selects all elements from inputCollection which don't match the given
+     * predicate into an output collection.
+     * <p>
+     * If the input predicate is {@code null}, the result is an empty list.
+     *
+     * @param <E> the element type
+     * @param inputCollection the collection to get the input from, may not be null
+     * @param predicate the predicate to use, may be null
+     * @return the elements <b>not</b> matching the predicate (new list)
+     * @throws NullPointerException if the input collection is null
+     *
+     * @since 4.0
+     * @see CollectionUtils#selectRejected(Iterable, Predicate)
+     */
+    public static <E> List<E> selectRejected(final Collection<? extends E> inputCollection,
+            final Predicate<? super E> predicate) {
+        return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList<E>(inputCollection.size()));
+    }
+
+    /**
+     * Subtracts all elements in the second list from the first list,
+     * placing the results in a new list.
+     * <p>
+     * This differs from {@link List#removeAll(Collection)} in that
+     * cardinality is respected; if <Code>list1</Code> contains two
+     * occurrences of <Code>null</Code> and <Code>list2</Code> only
+     * contains one occurrence, then the returned list will still contain
+     * one occurrence.
+     *
+     * @param <E> the element type
+     * @param list1  the list to subtract from
+     * @param list2  the list to subtract
+     * @return a new list containing the results
+     * @throws NullPointerException if either list is null
+     */
+    public static <E> List<E> subtract(final List<E> list1, final List<? extends E> list2) {
+        final ArrayList<E> result = new ArrayList<>();
+        final HashBag<E> bag = new HashBag<>(list2);
+        for (final E e : list1) {
+            if (!bag.remove(e, 1)) {
+                result.add(e);
+            }
+        }
+        return result;
+    }
+
+    /**
+     * Returns the sum of the given lists.  This is their intersection
+     * subtracted from their union.
+     *
+     * @param <E> the element type
+     * @param list1  the first list
+     * @param list2  the second list
+     * @return  a new list containing the sum of those lists
+     * @throws NullPointerException if either list is null
+     */
+    public static <E> List<E> sum(final List<? extends E> list1, final List<? extends E> list2) {
+        return subtract(union(list1, list2), intersection(list1, list2));
+    }
+
+    /**
      * Returns a synchronized list backed by the given list.
      * <p>
      * You must manually synchronize on the returned list's iterator to
@@ -378,38 +658,6 @@ public class ListUtils {
     }
 
     /**
-     * Returns an unmodifiable list backed by the given list.
-     * <p>
-     * This method uses the implementation in the decorators subpackage.
-     *
-     * @param <E>  the element type
-     * @param list  the list to make unmodifiable, must not be null
-     * @return an unmodifiable list backed by the given list
-     * @throws NullPointerException if the list is null
-     */
-    public static <E> List<E> unmodifiableList(final List<? extends E> list) {
-        return UnmodifiableList.unmodifiableList(list);
-    }
-
-    /**
-     * Returns a predicated (validating) list backed by the given list.
-     * <p>
-     * Only objects that pass the test in the given predicate can be added to the list.
-     * Trying to add an invalid object results in an IllegalArgumentException.
-     * It is important not to use the original list after invoking this method,
-     * as it is a backdoor for adding invalid objects.
-     *
-     * @param <E> the element type
-     * @param list  the list to predicate, must not be null
-     * @param predicate  the predicate for the list, must not be null
-     * @return a predicated list backed by the given list
-     * @throws NullPointerException if the List or Predicate is null
-     */
-    public static <E> List<E> predicatedList(final List<E> list, final Predicate<E> predicate) {
-        return PredicatedList.predicatedList(list, predicate);
-    }
-
-    /**
      * Returns a transformed list backed by the given list.
      * <p>
      * This method returns a new list (decorating the specified list) that
@@ -435,287 +683,39 @@ public class ListUtils {
     }
 
     /**
-     * Returns a "lazy" list whose elements will be created on demand.
-     * <p>
-     * When the index passed to the returned list's {@link List#get(int) get}
-     * method is greater than the list's size, then the factory will be used
-     * to create a new object and that object will be inserted at that index.
-     * <p>
-     * For instance:
-     *
-     * <pre>
-     * Factory&lt;Date&gt; factory = new Factory&lt;Date&gt;() {
-     *     public Date create() {
-     *         return new Date();
-     *     }
-     * }
-     * List&lt;Date&gt; lazy = ListUtils.lazyList(new ArrayList&lt;Date&gt;(), factory);
-     * Date date = lazy.get(3);
-     * </pre>
-     *
-     * After the above code is executed, {@code date} will refer to
-     * a new {@code Date} instance. Furthermore, that {@code Date}
-     * instance is the fourth element in the list.  The first, second,
-     * and third element are all set to {@code null}.
-     *
-     * @param <E> the element type
-     * @param list  the list to make lazy, must not be null
-     * @param factory  the factory for creating new objects, must not be null
-     * @return a lazy list backed by the given list
-     * @throws NullPointerException if the List or Factory is null
-     */
-    public static <E> List<E> lazyList(final List<E> list, final Factory<? extends E> factory) {
-        return LazyList.lazyList(list, factory);
-    }
-
-    /**
-     * Returns a "lazy" list whose elements will be created on demand.
-     * <p>
-     * When the index passed to the returned list's {@link List#get(int) get}
-     * method is greater than the list's size, then the transformer will be used
-     * to create a new object and that object will be inserted at that index.
-     * <p>
-     * For instance:
-     *
-     * <pre>
-     * List&lt;Integer&gt; hours = Arrays.asList(7, 5, 8, 2);
-     * Transformer&lt;Integer,Date&gt; transformer = input -&gt; LocalDateTime.now().withHour(hours.get(input));
-     * List&lt;LocalDateTime&gt; lazy = ListUtils.lazyList(new ArrayList&lt;LocalDateTime&gt;(), transformer);
-     * Date date = lazy.get(3);
-     * </pre>
-     *
-     * After the above code is executed, {@code date} will refer to
-     * a new {@code Date} instance. Furthermore, that {@code Date}
-     * instance is the fourth element in the list.  The first, second,
-     * and third element are all set to {@code null}.
+     * Returns a new list containing the second list appended to the
+     * first list.  The {@link List#addAll(Collection)} operation is
+     * used to append the two given lists into a new list.
      *
      * @param <E> the element type
-     * @param list  the list to make lazy, must not be null
-     * @param transformer  the transformer for creating new objects, must not be null
-     * @return a lazy list backed by the given list
-     * @throws NullPointerException if the List or Transformer is null
-     */
-    public static <E> List<E> lazyList(final List<E> list, final Transformer<Integer, ? extends E> transformer) {
-        return LazyList.lazyList(list, transformer);
-    }
-
-    /**
-     * Returns a fixed-sized list backed by the given list.
-     * Elements may not be added or removed from the returned list, but
-     * existing elements can be changed (for instance, via the
-     * {@link List#set(int, Object)} method).
-     *
-     * @param <E>  the element type
-     * @param list  the list whose size to fix, must not be null
-     * @return a fixed-size list backed by that list
-     * @throws NullPointerException  if the List is null
+     * @param list1  the first list
+     * @param list2  the second list
+     * @return a new list containing the union of those lists
+     * @throws NullPointerException if either list is null
      */
-    public static <E> List<E> fixedSizeList(final List<E> list) {
-        return FixedSizeList.fixedSizeList(list);
+    public static <E> List<E> union(final List<? extends E> list1, final List<? extends E> list2) {
+        final ArrayList<E> result = new ArrayList<>(list1.size() + list2.size());
+        result.addAll(list1);
+        result.addAll(list2);
+        return result;
     }
 
     /**
-     * Finds the first index in the given List which matches the given predicate.
+     * Returns an unmodifiable list backed by the given list.
      * <p>
-     * If the input List or predicate is null, or no element of the List
-     * matches the predicate, -1 is returned.
-     *
-     * @param <E>  the element type
-     * @param list the List to search, may be null
-     * @param predicate  the predicate to use, may be null
-     * @return the first index of an Object in the List which matches the predicate or -1 if none could be found
-     */
-    public static <E> int indexOf(final List<E> list, final Predicate<E> predicate) {
-        if (list != null && predicate != null) {
-            for (int i = 0; i < list.size(); i++) {
-                final E item = list.get(i);
-                if (predicate.evaluate(item)) {
-                    return i;
-                }
-            }
-        }
-        return CollectionUtils.INDEX_NOT_FOUND;
-    }
-
-    /**
-     * Returns the longest common subsequence (LCS) of two sequences (lists).
-     *
-     * @param <E>  the element type
-     * @param a  the first list
-     * @param b  the second list
-     * @return the longest common subsequence
-     * @throws NullPointerException if either list is {@code null}
-     * @since 4.0
-     */
-    public static <E> List<E> longestCommonSubsequence(final List<E> a, final List<E> b) {
-        return longestCommonSubsequence( a, b, DefaultEquator.defaultEquator() );
-    }
-
-    /**
-     * Returns the longest common subsequence (LCS) of two sequences (lists).
+     * This method uses the implementation in the decorators subpackage.
      *
      * @param <E>  the element type
-     * @param listA  the first list
-     * @param listB  the second list
-     * @param equator  the equator used to test object equality
-     * @return the longest common subsequence
-     * @throws NullPointerException if either list or the equator is {@code null}
-     * @since 4.0
-     */
-    public static <E> List<E> longestCommonSubsequence(final List<E> listA, final List<E> listB,
-                                                       final Equator<? super E> equator) {
-        Objects.requireNonNull(listA, "listA");
-        Objects.requireNonNull(listB, "listB");
-        Objects.requireNonNull(equator, "equator");
-
-        final SequencesComparator<E> comparator = new SequencesComparator<>(listA, listB, equator);
-        final EditScript<E> script = comparator.getScript();
-        final LcsVisitor<E> visitor = new LcsVisitor<>();
-        script.visit(visitor);
-        return visitor.getSubSequence();
-    }
-
-    /**
-     * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects.
-     * <p>
-     * This is a convenience method for using {@link #longestCommonSubsequence(List, List)}
-     * with {@link CharSequence} instances.
-     *
-     * @param charSequenceA  the first sequence
-     * @param charSequenceB  the second sequence
-     * @return the longest common subsequence as {@link String}
-     * @throws NullPointerException if either sequence is {@code null}
-     * @since 4.0
-     */
-    public static String longestCommonSubsequence(final CharSequence charSequenceA, final CharSequence charSequenceB) {
-        Objects.requireNonNull(charSequenceA, "charSequenceA");
-        Objects.requireNonNull(charSequenceB, "charSequenceB");
-        final List<Character> lcs = longestCommonSubsequence(new CharSequenceAsList(charSequenceA),
-                new CharSequenceAsList(charSequenceB));
-        final StringBuilder sb = new StringBuilder();
-        for (final Character ch : lcs) {
-            sb.append(ch);
-        }
-        return sb.toString();
-    }
-
-    /**
-     * A helper class used to construct the longest common subsequence.
-     */
-    private static final class LcsVisitor<E> implements CommandVisitor<E> {
-        private final ArrayList<E> sequence;
-
-        LcsVisitor() {
-            sequence = new ArrayList<>();
-        }
-
-        @Override
-        public void visitInsertCommand(final E object) {
-            // noop
-        }
-
-        @Override
-        public void visitDeleteCommand(final E object) {
-            // noop
-        }
-
-        @Override
-        public void visitKeepCommand(final E object) {
-            sequence.add(object);
-        }
-
-        public List<E> getSubSequence() {
-            return sequence;
-        }
-    }
-
-    /**
-     * A simple wrapper to use a CharSequence as List.
-     */
-    private static final class CharSequenceAsList extends AbstractList<Character> {
-        private final CharSequence sequence;
-
-        CharSequenceAsList(final CharSequence sequence) {
-            this.sequence = sequence;
-        }
-
-        @Override
-        public Character get(final int index) {
-            return Character.valueOf(sequence.charAt(index));
-        }
-
-        @Override
-        public int size() {
-            return sequence.length();
-        }
-    }
-
-    /**
-     * Returns consecutive {@link List#subList(int, int) sublists} of a
-     * list, each of the same size (the final list may be smaller). For example,
-     * partitioning a list containing {@code [a, b, c, d, e]} with a partition
-     * size of 3 yields {@code [[a, b, c], [d, e]]} -- an outer list containing
-     * two inner lists of three and two elements, all in the original order.
-     * <p>
-     * The outer list is unmodifiable, but reflects the latest state of the
-     * source list. The inner lists are sublist views of the original list,
-     * produced on demand using {@link List#subList(int, int)}, and are subject
-     * to all the usual caveats about modification as explained in that API.
-     * <p>
-     * Adapted from http://code.google.com/p/guava-libraries/
-     *
-     * @param <T> the element type
-     * @param list  the list to return consecutive sublists of
-     * @param size  the desired size of each sublist (the last may be smaller)
-     * @return a list of consecutive sublists
-     * @throws NullPointerException if list is null
-     * @throws IllegalArgumentException if size is not strictly positive
-     * @since 4.0
+     * @param list  the list to make unmodifiable, must not be null
+     * @return an unmodifiable list backed by the given list
+     * @throws NullPointerException if the list is null
      */
-    public static <T> List<List<T>> partition(final List<T> list, final int size) {
-        Objects.requireNonNull(list, "list");
-        if (size <= 0) {
-            throw new IllegalArgumentException("Size must be greater than 0");
-        }
-        return new Partition<>(list, size);
+    public static <E> List<E> unmodifiableList(final List<? extends E> list) {
+        return UnmodifiableList.unmodifiableList(list);
     }
 
     /**
-     * Provides a partition view on a {@link List}.
-     * @since 4.0
+     * Don't allow instances.
      */
-    private static class Partition<T> extends AbstractList<List<T>> {
-        private final List<T> list;
-        private final int size;
-
-        private Partition(final List<T> list, final int size) {
-            this.list = list;
-            this.size = size;
-        }
-
-        @Override
-        public List<T> get(final int index) {
-            final int listSize = size();
-            if (index < 0) {
-                throw new IndexOutOfBoundsException("Index " + index + " must not be negative");
-            }
-            if (index >= listSize) {
-                throw new IndexOutOfBoundsException("Index " + index + " must be less than size " +
-                                                    listSize);
-            }
-            final int start = index * size;
-            final int end = Math.min(start + size, list.size());
-            return list.subList(start, end);
-        }
-
-        @Override
-        public int size() {
-            return (int) Math.ceil((double) list.size() / (double) size);
-        }
-
-        @Override
-        public boolean isEmpty() {
-            return list.isEmpty();
-        }
-    }
+    private ListUtils() {}
 }
diff --git a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
index 4ab2c6d..11ccd02 100644
--- a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
+++ b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
@@ -43,7 +43,9 @@ public class ListUtilsTest {
     private static final String e = "e";
     private static final String x = "x";
 
+    private static final Predicate<Number> EQUALS_TWO = input -> input.intValue() == 2;
     private String[] fullArray;
+
     private List<String> fullList;
 
     @BeforeEach
@@ -52,13 +54,69 @@ public class ListUtilsTest {
         fullList = new ArrayList<>(Arrays.asList(fullArray));
     }
 
+    @Test
+    public void testDefaultIfNull() {
+        assertTrue(ListUtils.defaultIfNull(null, Collections.emptyList()).isEmpty());
+
+        final List<Long> list = new ArrayList<>();
+        assertSame(list, ListUtils.defaultIfNull(list, Collections.<Long>emptyList()));
+    }
+
+    @Test
+    public void testEmptyIfNull() {
+        assertTrue(ListUtils.emptyIfNull(null).isEmpty());
+
+        final List<Long> list = new ArrayList<>();
+        assertSame(list, ListUtils.emptyIfNull(list));
+    }
+
+    @Test
+    public void testEquals() {
+        final Collection<String> data = Arrays.asList("a", "b", "c");
+
+        final List<String> a = new ArrayList<>( data );
+        final List<String> b = new ArrayList<>( data );
+
+        assertEquals(a, b);
+        assertTrue(ListUtils.isEqualList(a, b));
+        a.clear();
+        assertFalse(ListUtils.isEqualList(a, b));
+        assertFalse(ListUtils.isEqualList(a, null));
+        assertFalse(ListUtils.isEqualList(null, b));
+        assertTrue(ListUtils.isEqualList(null, null));
+    }
+
+    @Test
+    public void testHashCode() {
+        final Collection<String> data = Arrays.asList("a", "b", "c");
+
+        final List<String> a = new ArrayList<>(data);
+        final List<String> b = new ArrayList<>(data);
+
+        assertEquals(a.hashCode(), b.hashCode());
+        assertEquals(a.hashCode(), ListUtils.hashCodeForList(a));
+        assertEquals(b.hashCode(), ListUtils.hashCodeForList(b));
+        assertEquals(ListUtils.hashCodeForList(a), ListUtils.hashCodeForList(b));
+        a.clear();
+        assertNotEquals(ListUtils.hashCodeForList(a), ListUtils.hashCodeForList(b));
+        assertEquals(0, ListUtils.hashCodeForList(null));
+    }
+
     /**
-     * Tests intersecting a non-empty list with an empty list.
+     * Tests the {@code indexOf} method in {@code ListUtils} class..
      */
     @Test
-    public void testIntersectNonEmptyWithEmptyList() {
-        final List<String> empty = Collections.<String>emptyList();
-        assertTrue(ListUtils.intersection(empty, fullList).isEmpty(), "result not empty");
+    public void testIndexOf() {
+        Predicate<String> testPredicate = EqualPredicate.equalPredicate("d");
+        int index = ListUtils.indexOf(fullList, testPredicate);
+        assertEquals(d, fullList.get(index));
+
+        testPredicate = EqualPredicate.equalPredicate("de");
+        index = ListUtils.indexOf(fullList, testPredicate);
+        assertEquals(index, -1);
+
+        assertEquals(ListUtils.indexOf(null, testPredicate), -1);
+        assertEquals(ListUtils.indexOf(fullList, null), -1);
     }
 
     /**
@@ -71,19 +129,19 @@ public class ListUtilsTest {
     }
 
     /**
-     * Tests intersecting a non-empty list with an subset of itself.
+     * Tests intersecting two lists in different orders.
      */
     @Test
-    public void testIntersectNonEmptySubset() {
-        // create a copy
-        final List<String> other = new ArrayList<>(fullList);
-
-        // remove a few items
-        assertNotNull(other.remove(0));
-        assertNotNull(other.remove(1));
-
-        // make sure the intersection is equal to the copy
-        assertEquals(other, ListUtils.intersection(fullList, other));
+    public void testIntersectionOrderInsensitivity() {
+        final List<String> one = new ArrayList<>();
+        final List<String> two = new ArrayList<>();
+        one.add("a");
+        one.add("b");
+        two.add("a");
+        two.add("a");
+        two.add("b");
+        two.add("b");
+        assertEquals(ListUtils.intersection(one, two), ListUtils.intersection(two, one));
     }
 
     /**
@@ -105,38 +163,28 @@ public class ListUtilsTest {
     }
 
     /**
-     * Tests intersecting two lists in different orders.
+     * Tests intersecting a non-empty list with an subset of itself.
      */
     @Test
-    public void testIntersectionOrderInsensitivity() {
-        final List<String> one = new ArrayList<>();
-        final List<String> two = new ArrayList<>();
-        one.add("a");
-        one.add("b");
-        two.add("a");
-        two.add("a");
-        two.add("b");
-        two.add("b");
-        assertEquals(ListUtils.intersection(one, two), ListUtils.intersection(two, one));
+    public void testIntersectNonEmptySubset() {
+        // create a copy
+        final List<String> other = new ArrayList<>(fullList);
+
+        // remove a few items
+        assertNotNull(other.remove(0));
+        assertNotNull(other.remove(1));
+
+        // make sure the intersection is equal to the copy
+        assertEquals(other, ListUtils.intersection(fullList, other));
     }
 
+    /**
+     * Tests intersecting a non-empty list with an empty list.
+     */
     @Test
-    public void testPredicatedList() {
-        final Predicate<Object> predicate = o -> o instanceof String;
-        final List<Object> list = ListUtils.predicatedList(new ArrayList<>(), predicate);
-        assertTrue(list instanceof PredicatedList, "returned object should be a PredicatedList");
-        try {
-            ListUtils.predicatedList(new ArrayList<>(), null);
-            fail("Expecting IllegalArgumentException for null predicate.");
-        } catch (final NullPointerException ex) {
-            // expected
-        }
-        try {
-            ListUtils.predicatedList(null, predicate);
-            fail("Expecting IllegalArgumentException for null list.");
-        } catch (final NullPointerException ex) {
-            // expected
-        }
+    public void testIntersectNonEmptyWithEmptyList() {
+        final List<String> empty = Collections.<String>emptyList();
+        assertTrue(ListUtils.intersection(empty, fullList).isEmpty(), "result not empty");
     }
 
     @Test
@@ -181,158 +229,6 @@ public class ListUtilsTest {
     }
 
     @Test
-    public void testEmptyIfNull() {
-        assertTrue(ListUtils.emptyIfNull(null).isEmpty());
-
-        final List<Long> list = new ArrayList<>();
-        assertSame(list, ListUtils.emptyIfNull(list));
-    }
-
-    @Test
-    public void testDefaultIfNull() {
-        assertTrue(ListUtils.defaultIfNull(null, Collections.emptyList()).isEmpty());
-
-        final List<Long> list = new ArrayList<>();
-        assertSame(list, ListUtils.defaultIfNull(list, Collections.<Long>emptyList()));
-    }
-
-    @Test
-    public void testEquals() {
-        final Collection<String> data = Arrays.asList("a", "b", "c");
-
-        final List<String> a = new ArrayList<>( data );
-        final List<String> b = new ArrayList<>( data );
-
-        assertEquals(a, b);
-        assertTrue(ListUtils.isEqualList(a, b));
-        a.clear();
-        assertFalse(ListUtils.isEqualList(a, b));
-        assertFalse(ListUtils.isEqualList(a, null));
-        assertFalse(ListUtils.isEqualList(null, b));
-        assertTrue(ListUtils.isEqualList(null, null));
-    }
-
-    @Test
-    public void testHashCode() {
-        final Collection<String> data = Arrays.asList("a", "b", "c");
-
-        final List<String> a = new ArrayList<>(data);
-        final List<String> b = new ArrayList<>(data);
-
-        assertEquals(a.hashCode(), b.hashCode());
-        assertEquals(a.hashCode(), ListUtils.hashCodeForList(a));
-        assertEquals(b.hashCode(), ListUtils.hashCodeForList(b));
-        assertEquals(ListUtils.hashCodeForList(a), ListUtils.hashCodeForList(b));
-        a.clear();
-        assertNotEquals(ListUtils.hashCodeForList(a), ListUtils.hashCodeForList(b));
-        assertEquals(0, ListUtils.hashCodeForList(null));
-    }
-
-    @Test
-    public void testRetainAll() {
-        final List<String> sub = new ArrayList<>();
-        sub.add(a);
-        sub.add(b);
-        sub.add(x);
-
-        final List<String> retained = ListUtils.retainAll(fullList, sub);
-        assertEquals(2, retained.size());
-        sub.remove(x);
-        assertEquals(retained, sub);
-        fullList.retainAll(sub);
-        assertEquals(retained, fullList);
-
-        try {
-            ListUtils.retainAll(null, null);
-            fail("expecting NullPointerException");
-        } catch(final NullPointerException npe){} // this is what we want
-    }
-
-    @Test
-    public void testRemoveAll() {
-        final List<String> sub = new ArrayList<>();
-        sub.add(a);
-        sub.add(b);
-        sub.add(x);
-
-        final List<String> remainder = ListUtils.removeAll(fullList, sub);
-        assertEquals(3, remainder.size());
-        fullList.removeAll(sub);
-        assertEquals(remainder, fullList);
-
-        try {
-            ListUtils.removeAll(null, null);
-            fail("expecting NullPointerException");
-        } catch(final NullPointerException npe) {} // this is what we want
-    }
-
-    @Test
-    public void testSubtract() {
-        final List<String> list = new ArrayList<>();
-        list.add(a);
-        list.add(b);
-        list.add(a);
-        list.add(x);
-
-        final List<String> sub = new ArrayList<>();
-        sub.add(a);
-
-        final List<String> result = ListUtils.subtract(list, sub);
-        assertEquals(3, result.size());
-
-        final List<String> expected = new ArrayList<>();
-        expected.add(b);
-        expected.add(a);
-        expected.add(x);
-
-        assertEquals(expected, result);
-
-        try {
-            ListUtils.subtract(list, null);
-            fail("expecting NullPointerException");
-        } catch(final NullPointerException npe) {} // this is what we want
-    }
-
-    @Test
-    public void testSubtractNullElement() {
-        final List<String> list = new ArrayList<>();
-        list.add(a);
-        list.add(null);
-        list.add(null);
-        list.add(x);
-
-        final List<String> sub = new ArrayList<>();
-        sub.add(null);
-
-        final List<String> result = ListUtils.subtract(list, sub);
-        assertEquals(3, result.size());
-
-        final List<String> expected = new ArrayList<>();
-        expected.add(a);
-        expected.add(null);
-        expected.add(x);
-
-        assertEquals(expected, result);
-    }
-
-    /**
-     * Tests the {@code indexOf} method in {@code ListUtils} class..
-     */
-    @Test
-    public void testIndexOf() {
-        Predicate<String> testPredicate = EqualPredicate.equalPredicate("d");
-        int index = ListUtils.indexOf(fullList, testPredicate);
-        assertEquals(d, fullList.get(index));
-
-        testPredicate = EqualPredicate.equalPredicate("de");
-        index = ListUtils.indexOf(fullList, testPredicate);
-        assertEquals(index, -1);
-
-        assertEquals(ListUtils.indexOf(null, testPredicate), -1);
-        assertEquals(ListUtils.indexOf(fullList, null), -1);
-    }
-
-    @Test
     @SuppressWarnings("boxing") // OK in test code
     public void testLongestCommonSubsequence() {
 
@@ -447,7 +343,62 @@ public class ListUtilsTest {
         assertEquals(strings, partitionMax.get(0));
     }
 
-    private static final Predicate<Number> EQUALS_TWO = input -> input.intValue() == 2;
+    @Test
+    public void testPredicatedList() {
+        final Predicate<Object> predicate = o -> o instanceof String;
+        final List<Object> list = ListUtils.predicatedList(new ArrayList<>(), predicate);
+        assertTrue(list instanceof PredicatedList, "returned object should be a PredicatedList");
+        try {
+            ListUtils.predicatedList(new ArrayList<>(), null);
+            fail("Expecting IllegalArgumentException for null predicate.");
+        } catch (final NullPointerException ex) {
+            // expected
+        }
+        try {
+            ListUtils.predicatedList(null, predicate);
+            fail("Expecting IllegalArgumentException for null list.");
+        } catch (final NullPointerException ex) {
+            // expected
+        }
+    }
+
+    @Test
+    public void testRemoveAll() {
+        final List<String> sub = new ArrayList<>();
+        sub.add(a);
+        sub.add(b);
+        sub.add(x);
+
+        final List<String> remainder = ListUtils.removeAll(fullList, sub);
+        assertEquals(3, remainder.size());
+        fullList.removeAll(sub);
+        assertEquals(remainder, fullList);
+
+        try {
+            ListUtils.removeAll(null, null);
+            fail("expecting NullPointerException");
+        } catch(final NullPointerException npe) {} // this is what we want
+    }
+
+    @Test
+    public void testRetainAll() {
+        final List<String> sub = new ArrayList<>();
+        sub.add(a);
+        sub.add(b);
+        sub.add(x);
+
+        final List<String> retained = ListUtils.retainAll(fullList, sub);
+        assertEquals(2, retained.size());
+        sub.remove(x);
+        assertEquals(retained, sub);
+        fullList.retainAll(sub);
+        assertEquals(retained, fullList);
+
+        try {
+            ListUtils.retainAll(null, null);
+            fail("expecting NullPointerException");
+        } catch(final NullPointerException npe){} // this is what we want
+    }
 
     @Test
     @SuppressWarnings("boxing") // OK in test code
@@ -486,4 +437,53 @@ public class ListUtilsTest {
         assertTrue(output1.contains(3L));
         assertTrue(output1.contains(4L));
     }
+
+    @Test
+    public void testSubtract() {
+        final List<String> list = new ArrayList<>();
+        list.add(a);
+        list.add(b);
+        list.add(a);
+        list.add(x);
+
+        final List<String> sub = new ArrayList<>();
+        sub.add(a);
+
+        final List<String> result = ListUtils.subtract(list, sub);
+        assertEquals(3, result.size());
+
+        final List<String> expected = new ArrayList<>();
+        expected.add(b);
+        expected.add(a);
+        expected.add(x);
+
+        assertEquals(expected, result);
+
+        try {
+            ListUtils.subtract(list, null);
+            fail("expecting NullPointerException");
+        } catch(final NullPointerException npe) {} // this is what we want
+    }
+
+    @Test
+    public void testSubtractNullElement() {
+        final List<String> list = new ArrayList<>();
+        list.add(a);
+        list.add(null);
+        list.add(null);
+        list.add(x);
+
+        final List<String> sub = new ArrayList<>();
+        sub.add(null);
+
+        final List<String> result = ListUtils.subtract(list, sub);
+        assertEquals(3, result.size());
+
+        final List<String> expected = new ArrayList<>();
+        expected.add(a);
+        expected.add(null);
+        expected.add(x);
+
+        assertEquals(expected, result);
+    }
 }

[commons-collections] 02/03: Sort by type.

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit 09d8151cee874bf72adf524503f9e8adb57db2ec
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Aug 2 13:35:55 2021 -0400

    Sort by type.
---
 src/changes/changes.xml | 113 +++++++++++++++++++++++++-----------------------
 1 file changed, 58 insertions(+), 55 deletions(-)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index ce54b6b..4667ae8 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -21,10 +21,11 @@
   </properties>
   <body>
   <release version="4.5" date="2020-MM-DD" description="Maintenance release.">
-  	<action issue="COLLECTIONS-780" dev="kinow" type="fix" due-to="Arturo Bernal">
+    <!-- FIX -->
+    <action issue="COLLECTIONS-780" dev="kinow" type="fix" due-to="Arturo Bernal">
       Use assertThrows V2.
     </action>
-  	<action issue="COLLECTIONS-778" dev="kinow" type="fix" due-to="Arturo Bernal">
+    <action issue="COLLECTIONS-778" dev="kinow" type="fix" due-to="Arturo Bernal">
       Use assertThrows.
     </action>
     <action issue="COLLECTIONS-771" dev="kinow" type="fix" due-to="Xin Tong">
@@ -33,9 +34,6 @@
     <action issue="COLLECTIONS-769" dev="kinow" type="fix" due-to="Xin (Cynthia) Tong">
       Fix flaky UnmodifiableMultiValuedMapTest.
     </action>
-    <action type="update" dev="kinow" due-to="Dependabot">
-      Bump actions/setup-java from v1.4.0 to v2 #174 #177 #186 #224.
-    </action>
     <action issue="COLLECTIONS-764" dev="kinow" type="fix" due-to="XenoAmess">
       Refine javadoc and fix typos.
     </action>
@@ -48,24 +46,6 @@
     <action issue="COLLECTIONS-759" dev="kinow" type="fix">
       Fix checkstyle issues regarding missing newline at end of file, and CRLF vs LF.
     </action>
-    <action issue="COLLECTIONS-760" dev="kinow" type="add" due-to="Isira Seneviratne">
-      Add tests for MapUtils
-    </action>
-    <action issue="COLLECTIONS-737" dev="kinow" type="update" due-to="Prodigysov">
-      Return 0 immediately if the given iterable is null in IterableUtils#size. Update tests.
-    </action>
-    <action issue="COLLECTIONS-697" dev="eax" type="update" due-to="Ranjan George">
-      JavaDoc for FixedSizeList should warn that modifying underlying list is still allowed and is not prevented
-    </action>
-    <action issue="COLLECTIONS-738" dev="kinow" type="update" due-to="Pengyu Nie">
-      Remove the redundant assertNull in IterableUtilsTest.find and update Javadocs.
-    </action>
-    <action issue="COLLECTIONS-724" dev="ggregory" type="update" due-to="Eitan Adler">
-      Simplify two remove-if loops #77.
-    </action>
-    <action issue="COLLECTIONS-726" dev="ggregory" type="update" due-to="liuhaozzu, Gary Gregory">
-      Add lambdas function to provide default values in MapUtils #81.
-    </action>
     <action issue="COLLECTIONS-727" dev="ggregory" type="fix" due-to="XiangzheXu, XZ-X">
       A potential misleading comment #82.
     </action>
@@ -78,8 +58,24 @@
     <action dev="ggregory" type="fix" due-to="dota17">
       Fix typos in release notes and Javadoc for AbstractHashedMap and AbstractHashedMapTest #88.
     </action>
-    <action issue="COLLECTIONS-704" dev="ggregory" type="update" due-to="dota17">
-      Update size to capacity for GrowthList #90.
+    <action issue="COLLECTIONS-740" dev="ggregory" type="fix" due-to="Pengyu Nie">
+      Add missing @throws comment for SwitchTransformer.switchTransformer. #124.
+    </action>
+    <action issue="COLLECTIONS-739" dev="ggregory" type="fix" due-to="Pengyu Nie">
+      Fix inconsistent @throws comments in DefaultedMap #123.
+    </action>
+    <action dev="ggregory" type="fix" due-to="Dominik Stadler">
+      Fix links to release notes and update contents for 4.4 #127.
+    </action>
+    <action type="fix" dev="kinow" due-to="Jin Xu">
+      Fix checkstyle syntax (was scope, is now accessModifiers) via PR #235.
+    </action>
+    <action issue="COLLECTIONS-786" type="fix" dev="kinow" due-to="vandrewskis">
+      Fix PassiveExpiringMap documentation for methods that involve accessing the entire map.
+    </action>
+    <!-- ADD -->
+    <action issue="COLLECTIONS-760" dev="kinow" type="add" due-to="Isira Seneviratne">
+      Add tests for MapUtils.
     </action>
     <action dev="ggregory" type="add" due-to="dota17">
       Test subMap and tailMap #94.
@@ -93,27 +89,12 @@
     <action dev="ggregory" type="add" due-to="dota17">
       Update two test cases in AbstractMultiValuedMapTest testPutAll_map1 testPutAll_map2 #97.
     </action>
-    <action dev="ggregory" type="update" due-to="dota17">
-      TransformedSortedBagTest should work with TransformedSortedBag, not TransformedBag #98.
-    </action>
     <action dev="ggregory" type="add" due-to="dota17">
       Add a test case for AbstractMultiValuedMapTest testToString() #100.
     </action>
-    <action dev="ggregory" type="update" due-to="dota17">
-      Update some map test cases #104.
-    </action>
-    <action dev="ggregory" type="update" due-to="dota17">
-      Add three test cases in UnmodifiableQueueTest #105.
-    </action>
-    <action issue="COLLECTIONS-674" dev="ggregory" type="add" due-to="dota17">
-      Add CollectionUtils removeRange, removeCount #91.
-    </action>
     <action dev="ggregory" type="add" due-to="dota17">
       Add a test case AbstractMultiValuedMapTest#testMultiValuedMapIterator() #108.
     </action>
-    <action dev="ggregory" type="update" due-to="dota17">
-      Remove the parentheses in the error message in CircularFifoQueue #107.
-    </action>
     <action dev="ggregory" type="add" due-to="dota17">
       Add junit for getWithNull and subList in LazyListTest; #103.
     </action>
@@ -122,6 +103,43 @@
     </action>
     <action dev="ggregory" type="add" due-to="dota17">
       Add test cases in UnmodifiableMultiValuedMapTest; #102.
+    </action>    
+    <action issue="COLLECTIONS-674" dev="ggregory" type="add" due-to="dota17">
+      Add CollectionUtils removeRange, removeCount #91.
+    </action>
+    <!-- UPDATE -->
+    <action type="update" dev="kinow" due-to="Dependabot">
+      Bump actions/setup-java from v1.4.0 to v2 #174 #177 #186 #224.
+    </action>
+    <action issue="COLLECTIONS-737" dev="kinow" type="update" due-to="Prodigysov">
+      Return 0 immediately if the given iterable is null in IterableUtils#size. Update tests.
+    </action>
+    <action issue="COLLECTIONS-697" dev="eax" type="update" due-to="Ranjan George">
+      JavaDoc for FixedSizeList should warn that modifying underlying list is still allowed and is not prevented
+    </action>
+    <action issue="COLLECTIONS-738" dev="kinow" type="update" due-to="Pengyu Nie">
+      Remove the redundant assertNull in IterableUtilsTest.find and update Javadocs.
+    </action>
+    <action issue="COLLECTIONS-724" dev="ggregory" type="update" due-to="Eitan Adler">
+      Simplify two remove-if loops #77.
+    </action>
+    <action issue="COLLECTIONS-726" dev="ggregory" type="update" due-to="liuhaozzu, Gary Gregory">
+      Add lambdas function to provide default values in MapUtils #81.
+    </action>
+    <action issue="COLLECTIONS-704" dev="ggregory" type="update" due-to="dota17">
+      Update size to capacity for GrowthList #90.
+    </action>
+    <action dev="ggregory" type="update" due-to="dota17">
+      TransformedSortedBagTest should work with TransformedSortedBag, not TransformedBag #98.
+    </action>
+    <action dev="ggregory" type="update" due-to="dota17">
+      Update some map test cases #104.
+    </action>
+    <action dev="ggregory" type="update" due-to="dota17">
+      Add three test cases in UnmodifiableQueueTest #105.
+    </action>
+    <action dev="ggregory" type="update" due-to="dota17">
+      Remove the parentheses in the error message in CircularFifoQueue #107.
     </action>
     <action dev="ggregory" type="update" due-to="Gary Gregory">
       [test] org.easymock:easymock 4.0.2 -> 4.1.
@@ -132,15 +150,6 @@
     <action dev="ggregory" type="update" due-to="Chen">
       Fix inconsistent @throws comments in ListOrderedSet #125.
     </action>
-    <action issue="COLLECTIONS-740" dev="ggregory" type="fix" due-to="Pengyu Nie">
-      Add missing @throws comment for SwitchTransformer.switchTransformer. #124.
-    </action>
-    <action issue="COLLECTIONS-739" dev="ggregory" type="fix" due-to="Pengyu Nie">
-      Fix inconsistent @throws comments in DefaultedMap #123.
-    </action>
-    <action dev="ggregory" type="fix" due-to="Dominik Stadler">
-      Fix links to release notes and update contents for 4.4 #127.
-    </action>
     <action issue="COLLECTIONS-744" dev="ggregory" type="add" due-to="Gary Gregory">
       Add org.apache.commons.collections4.EnumerationUtils.asIterable(Enumeration).
     </action>
@@ -266,12 +275,6 @@
     <action type="update" dev="kinow" due-to="Dependabot">
       Bump easymock from 4.2 to 4.3 #226.
     </action>
-    <action type="fix" dev="kinow" due-to="Jin Xu">
-      Fix checkstyle syntax (was scope, is now accessModifiers) via PR #235.
-    </action>
-    <action issue="COLLECTIONS-786" type="fix" dev="kinow" due-to="vandrewskis">
-      Fix PassiveExpiringMap documentation for methods that involve accessing the entire map.
-    </action>
   </release>
   <release version="4.4" date="2019-07-05" description="Maintenance release.">
     <action issue="COLLECTIONS-710" dev="ggregory" type="fix" due-to="Yu Shi, Gary Gregory">

[commons-collections] 03/03: Add ListUtils.getFirst() and getLast().

Posted by gg...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-collections.git

commit bfede0ea47eacb2e9787b2d98dce4216c304bf46
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Mon Aug 2 13:41:20 2021 -0400

    Add ListUtils.getFirst() and getLast().
---
 src/changes/changes.xml                            |  3 +++
 .../org/apache/commons/collections4/ListUtils.java | 30 ++++++++++++++++++++++
 .../apache/commons/collections4/ListUtilsTest.java | 14 ++++++++++
 3 files changed, 47 insertions(+)

diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 4667ae8..b664e7b 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -107,6 +107,9 @@
     <action issue="COLLECTIONS-674" dev="ggregory" type="add" due-to="dota17">
       Add CollectionUtils removeRange, removeCount #91.
     </action>
+    <action dev="ggregory" type="add" due-to="Gary Gregory">
+      Add ListUtils.getFirst() and getLast().
+    </action>
     <!-- UPDATE -->
     <action type="update" dev="kinow" due-to="Dependabot">
       Bump actions/setup-java from v1.4.0 to v2 #174 #177 #186 #224.
diff --git a/src/main/java/org/apache/commons/collections4/ListUtils.java b/src/main/java/org/apache/commons/collections4/ListUtils.java
index e8c3d8a..e8cec45 100644
--- a/src/main/java/org/apache/commons/collections4/ListUtils.java
+++ b/src/main/java/org/apache/commons/collections4/ListUtils.java
@@ -175,6 +175,36 @@ public class ListUtils {
     }
 
     /**
+     * Gets the first element of a list.
+     * <p>
+     * Shorthand for {@code list.get(0)}
+     * </p>
+     * @param <T> The list type.
+     * @param list The list
+     * @return the first element of a list.
+     * @see List#get(int)
+     * @since 4.5
+     */
+    public static <T> T getFirst(List<T> list) {
+        return Objects.requireNonNull(list, "list").get(0);
+    }
+
+    /**
+     * Gets the last element of a list.
+     * <p>
+     * Shorthand for {@code list.get(list.size() - 1)}
+     * </p>
+     * @param <T> The list type.
+     * @param list The list
+     * @return the last element of a list.
+     * @see List#get(int)
+     * @since 4.5
+     */
+    public static <T> T getLast(List<T> list) {
+        return Objects.requireNonNull(list, "list").get(list.size() - 1);
+    }
+
+    /**
      * Generates a hash code using the algorithm specified in
      * {@link java.util.List#hashCode()}.
      * <p>
diff --git a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
index 11ccd02..59d6860 100644
--- a/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
+++ b/src/test/java/org/apache/commons/collections4/ListUtilsTest.java
@@ -55,6 +55,20 @@ public class ListUtilsTest {
     }
 
     @Test
+    public void testGetFirst() {
+        assertEquals(a, ListUtils.getFirst(fullList));
+        assertThrows(NullPointerException.class, () -> ListUtils.getFirst(null));
+        assertThrows(IndexOutOfBoundsException.class, () -> ListUtils.getFirst(new ArrayList<>()));
+    }
+
+    @Test
+    public void testGetLast() {
+        assertEquals(e, ListUtils.getLast(fullList));
+        assertThrows(NullPointerException.class, () -> ListUtils.getFirst(null));
+        assertThrows(IndexOutOfBoundsException.class, () -> ListUtils.getFirst(new ArrayList<>()));
+    }
+
+    @Test
     public void testDefaultIfNull() {
         assertTrue(ListUtils.defaultIfNull(null, Collections.emptyList()).isEmpty());