From 90d2a9bcee6768e0c18ed1b9913c70aef8ff12d6 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Mon, 2 Aug 2021 13:23:50 -0400 Subject: [PATCH] Sort members. --- .../commons/collections4/ListUtils.java | 852 +++++++++--------- .../commons/collections4/ListUtilsTest.java | 390 ++++---- 2 files changed, 621 insertions(+), 621 deletions(-) diff --git a/src/main/java/org/apache/commons/collections4/ListUtils.java b/src/main/java/org/apache/commons/collections4/ListUtils.java index 548bf140e..e8c3d8ad7 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 { + 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 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 List emptyIfNull(final List list) { - return list == null ? Collections.emptyList() : list; + private static final class LcsVisitor implements CommandVisitor { + private final ArrayList sequence; + + LcsVisitor() { + sequence = new ArrayList<>(); + } + + public List 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 extends AbstractList> { + private final List list; + private final int size; + + private Partition(final List list, final int size) { + this.list = list; + this.size = size; + } + + @Override + public List 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); + } } /** @@ -74,6 +147,82 @@ public class ListUtils { return list == null ? defaultList : list; } + /** + * Returns an immutable empty list if the argument is {@code null}, + * or the argument itself otherwise. + * + * @param the element type + * @param list the list, possibly {@code null} + * @return an empty list if the argument is {@code null} + */ + public static List emptyIfNull(final List list) { + return list == null ? Collections.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 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 List fixedSizeList(final List list) { + return FixedSizeList.fixedSizeList(list); + } + + /** + * Generates a hash code using the algorithm specified in + * {@link java.util.List#hashCode()}. + *

+ * 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. + *

+ * If the input List or predicate is null, or no element of the List + * matches the predicate, -1 is returned. + * + * @param 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 int indexOf(final List list, final Predicate 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. @@ -105,105 +254,6 @@ public class ListUtils { return result; } - /** - * Subtracts all elements in the second list from the first list, - * placing the results in a new list. - *

- * This differs from {@link List#removeAll(Collection)} in that - * cardinality is respected; if list1 contains two - * occurrences of null and list2 only - * contains one occurrence, then the returned list will still contain - * one occurrence. - * - * @param 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 List subtract(final List list1, final List list2) { - final ArrayList result = new ArrayList<>(); - final HashBag 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 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 List sum(final List list1, final List list2) { - return subtract(union(list1, list2), intersection(list1, list2)); - } - - /** - * 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 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 - */ - public static List union(final List list1, final List list2) { - final ArrayList result = new ArrayList<>(list1.size() + list2.size()); - result.addAll(list1); - result.addAll(list2); - return result; - } - - /** - * Selects all elements from input collection which match the given - * predicate into an output list. - *

- * A {@code null} predicate matches no elements. - * - * @param 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 List select(final Collection inputCollection, - final Predicate predicate) { - return CollectionUtils.select(inputCollection, predicate, new ArrayList(inputCollection.size())); - } - - /** - * Selects all elements from inputCollection which don't match the given - * predicate into an output collection. - *

- * If the input predicate is {@code null}, the result is an empty list. - * - * @param 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 not matching the predicate (new list) - * @throws NullPointerException if the input collection is null - * - * @since 4.0 - * @see CollectionUtils#selectRejected(Iterable, Predicate) - */ - public static List selectRejected(final Collection inputCollection, - final Predicate predicate) { - return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList(inputCollection.size())); - } - /** * Tests two lists for value-equality as per the equality contract in * {@link java.util.List#equals(java.lang.Object)}. @@ -258,182 +308,6 @@ public class ListUtils { return !(it1.hasNext() || it2.hasNext()); } - /** - * Generates a hash code using the algorithm specified in - * {@link java.util.List#hashCode()}. - *

- * 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; - } - - /** - * 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);}. - *

- * 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 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 List retainAll(final Collection collection, final Collection retain) { - final List list = new ArrayList<>(Math.min(collection.size(), retain.size())); - - for (final E obj : collection) { - if (retain.contains(obj)) { - list.add(obj); - } - } - return list; - } - - /** - * Removes the elements in {@code remove} from {@code collection}. That is, this - * method returns a list containing all the elements in {@code collection} - * that are not in {@code remove}. The cardinality of an element {@code e} - * in the returned collection is the same as the cardinality of {@code e} - * in {@code collection} unless {@code remove} contains {@code e}, in which - * case the cardinality is zero. This method is useful if you do not wish to modify - * {@code collection} and thus cannot call {@code collection.removeAll(remove);}. - *

- * This implementation iterates over {@code collection}, checking each element in - * turn to see if it's contained in {@code remove}. If it's not contained, it's added - * to the returned list. As a consequence, it is advised to use a collection type for - * {@code remove} that provides a fast (e.g. O(1)) implementation of - * {@link Collection#contains(Object)}. - * - * @param the element type - * @param collection the collection from which items are removed (in the returned collection) - * @param remove the items to be removed from the returned {@code collection} - * @return a {@code List} containing all the elements of {@code c} except - * any elements that also occur in {@code remove}. - * @throws NullPointerException if either parameter is null - * @since 3.2 - */ - public static List removeAll(final Collection collection, final Collection remove) { - final List list = new ArrayList<>(); - for (final E obj : collection) { - if (!remove.contains(obj)) { - list.add(obj); - } - } - return list; - } - - /** - * Returns a synchronized list backed by the given list. - *

- * You must manually synchronize on the returned list's iterator to - * avoid non-deterministic behavior: - * - *

-     * List list = ListUtils.synchronizedList(myList);
-     * synchronized (list) {
-     *     Iterator i = list.iterator();
-     *     while (i.hasNext()) {
-     *         process (i.next());
-     *     }
-     * }
-     * 
- * - * This method is just a wrapper for {@link Collections#synchronizedList(List)}. - * - * @param the element type - * @param list the list to synchronize, must not be null - * @return a synchronized list backed by the given list - * @throws NullPointerException if the list is null - */ - public static List synchronizedList(final List list) { - return Collections.synchronizedList(list); - } - - /** - * Returns an unmodifiable list backed by the given list. - *

- * This method uses the implementation in the decorators subpackage. - * - * @param 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 List unmodifiableList(final List list) { - return UnmodifiableList.unmodifiableList(list); - } - - /** - * Returns a predicated (validating) list backed by the given list. - *

- * 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 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 List predicatedList(final List list, final Predicate predicate) { - return PredicatedList.predicatedList(list, predicate); - } - - /** - * Returns a transformed list backed by the given list. - *

- * This method returns a new list (decorating the specified list) that - * will transform any new entries added to it. - * Existing entries in the specified list will not be transformed. - *

- * Each object is passed through the transformer as it is added to the - * List. It is important not to use the original list after invoking this - * method, as it is a backdoor for adding untransformed objects. - *

- * Existing entries in the specified list will not be transformed. - * If you want that behavior, see {@link TransformedList#transformedList}. - * - * @param the element type - * @param list the list to predicate, must not be null - * @param transformer the transformer for the list, must not be null - * @return a transformed list backed by the given list - * @throws NullPointerException if the List or Transformer is null - */ - public static List transformedList(final List list, - final Transformer transformer) { - return TransformedList.transformingList(list, transformer); - } - /** * Returns a "lazy" list whose elements will be created on demand. *

@@ -500,41 +374,27 @@ public class ListUtils { } /** - * 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 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 List fixedSizeList(final List list) { - return FixedSizeList.fixedSizeList(list); - } - - /** - * Finds the first index in the given List which matches the given predicate. + * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects. *

- * If the input List or predicate is null, or no element of the List - * matches the predicate, -1 is returned. + * This is a convenience method for using {@link #longestCommonSubsequence(List, List)} + * with {@link CharSequence} instances. * - * @param 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 + * @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 int indexOf(final List list, final Predicate 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; - } - } + public static String longestCommonSubsequence(final CharSequence charSequenceA, final CharSequence charSequenceB) { + Objects.requireNonNull(charSequenceA, "charSequenceA"); + Objects.requireNonNull(charSequenceB, "charSequenceB"); + final List lcs = longestCommonSubsequence(new CharSequenceAsList(charSequenceA), + new CharSequenceAsList(charSequenceB)); + final StringBuilder sb = new StringBuilder(); + for (final Character ch : lcs) { + sb.append(ch); } - return CollectionUtils.INDEX_NOT_FOUND; + return sb.toString(); } /** @@ -575,81 +435,6 @@ public class ListUtils { return visitor.getSubSequence(); } - /** - * Returns the longest common subsequence (LCS) of two {@link CharSequence} objects. - *

- * 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 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 implements CommandVisitor { - private final ArrayList 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 getSubSequence() { - return sequence; - } - } - - /** - * A simple wrapper to use a CharSequence as List. - */ - private static final class CharSequenceAsList extends AbstractList { - 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, @@ -681,41 +466,256 @@ public class ListUtils { } /** - * Provides a partition view on a {@link List}. - * @since 4.0 + * Returns a predicated (validating) list backed by the given list. + *

+ * 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 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 */ - private static class Partition extends AbstractList> { - private final List list; - private final int size; - - private Partition(final List list, final int size) { - this.list = list; - this.size = size; - } - - @Override - public List 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(); - } + public static List predicatedList(final List list, final Predicate predicate) { + return PredicatedList.predicatedList(list, predicate); } + + /** + * Removes the elements in {@code remove} from {@code collection}. That is, this + * method returns a list containing all the elements in {@code collection} + * that are not in {@code remove}. The cardinality of an element {@code e} + * in the returned collection is the same as the cardinality of {@code e} + * in {@code collection} unless {@code remove} contains {@code e}, in which + * case the cardinality is zero. This method is useful if you do not wish to modify + * {@code collection} and thus cannot call {@code collection.removeAll(remove);}. + *

+ * This implementation iterates over {@code collection}, checking each element in + * turn to see if it's contained in {@code remove}. If it's not contained, it's added + * to the returned list. As a consequence, it is advised to use a collection type for + * {@code remove} that provides a fast (e.g. O(1)) implementation of + * {@link Collection#contains(Object)}. + * + * @param the element type + * @param collection the collection from which items are removed (in the returned collection) + * @param remove the items to be removed from the returned {@code collection} + * @return a {@code List} containing all the elements of {@code c} except + * any elements that also occur in {@code remove}. + * @throws NullPointerException if either parameter is null + * @since 3.2 + */ + public static List removeAll(final Collection collection, final Collection remove) { + final List list = new ArrayList<>(); + for (final E obj : collection) { + if (!remove.contains(obj)) { + list.add(obj); + } + } + return list; + } + + /** + * 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);}. + *

+ * 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 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 List retainAll(final Collection collection, final Collection retain) { + final List 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. + *

+ * A {@code null} predicate matches no elements. + * + * @param 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 List select(final Collection inputCollection, + final Predicate predicate) { + return CollectionUtils.select(inputCollection, predicate, new ArrayList(inputCollection.size())); + } + + /** + * Selects all elements from inputCollection which don't match the given + * predicate into an output collection. + *

+ * If the input predicate is {@code null}, the result is an empty list. + * + * @param 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 not matching the predicate (new list) + * @throws NullPointerException if the input collection is null + * + * @since 4.0 + * @see CollectionUtils#selectRejected(Iterable, Predicate) + */ + public static List selectRejected(final Collection inputCollection, + final Predicate predicate) { + return CollectionUtils.selectRejected(inputCollection, predicate, new ArrayList(inputCollection.size())); + } + + /** + * Subtracts all elements in the second list from the first list, + * placing the results in a new list. + *

+ * This differs from {@link List#removeAll(Collection)} in that + * cardinality is respected; if list1 contains two + * occurrences of null and list2 only + * contains one occurrence, then the returned list will still contain + * one occurrence. + * + * @param 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 List subtract(final List list1, final List list2) { + final ArrayList result = new ArrayList<>(); + final HashBag 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 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 List sum(final List list1, final List list2) { + return subtract(union(list1, list2), intersection(list1, list2)); + } + + /** + * Returns a synchronized list backed by the given list. + *

+ * You must manually synchronize on the returned list's iterator to + * avoid non-deterministic behavior: + * + *

+     * List list = ListUtils.synchronizedList(myList);
+     * synchronized (list) {
+     *     Iterator i = list.iterator();
+     *     while (i.hasNext()) {
+     *         process (i.next());
+     *     }
+     * }
+     * 
+ * + * This method is just a wrapper for {@link Collections#synchronizedList(List)}. + * + * @param the element type + * @param list the list to synchronize, must not be null + * @return a synchronized list backed by the given list + * @throws NullPointerException if the list is null + */ + public static List synchronizedList(final List list) { + return Collections.synchronizedList(list); + } + + /** + * Returns a transformed list backed by the given list. + *

+ * This method returns a new list (decorating the specified list) that + * will transform any new entries added to it. + * Existing entries in the specified list will not be transformed. + *

+ * Each object is passed through the transformer as it is added to the + * List. It is important not to use the original list after invoking this + * method, as it is a backdoor for adding untransformed objects. + *

+ * Existing entries in the specified list will not be transformed. + * If you want that behavior, see {@link TransformedList#transformedList}. + * + * @param the element type + * @param list the list to predicate, must not be null + * @param transformer the transformer for the list, must not be null + * @return a transformed list backed by the given list + * @throws NullPointerException if the List or Transformer is null + */ + public static List transformedList(final List list, + final Transformer transformer) { + return TransformedList.transformingList(list, transformer); + } + + /** + * 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 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 + */ + public static List union(final List list1, final List list2) { + final ArrayList result = new ArrayList<>(list1.size() + list2.size()); + result.addAll(list1); + result.addAll(list2); + return result; + } + + /** + * Returns an unmodifiable list backed by the given list. + *

+ * This method uses the implementation in the decorators subpackage. + * + * @param 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 List unmodifiableList(final List list) { + return UnmodifiableList.unmodifiableList(list); + } + + /** + * Don't allow instances. + */ + 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 4ab2c6df5..11ccd02a6 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 EQUALS_TWO = input -> input.intValue() == 2; private String[] fullArray; + private List 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 list = new ArrayList<>(); + assertSame(list, ListUtils.defaultIfNull(list, Collections.emptyList())); + } + + @Test + public void testEmptyIfNull() { + assertTrue(ListUtils.emptyIfNull(null).isEmpty()); + + final List list = new ArrayList<>(); + assertSame(list, ListUtils.emptyIfNull(list)); + } + + @Test + public void testEquals() { + final Collection data = Arrays.asList("a", "b", "c"); + + final List a = new ArrayList<>( data ); + final List 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 data = Arrays.asList("a", "b", "c"); + + final List a = new ArrayList<>(data); + final List 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 empty = Collections.emptyList(); - assertTrue(ListUtils.intersection(empty, fullList).isEmpty(), "result not empty"); + public void testIndexOf() { + Predicate 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 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 one = new ArrayList<>(); + final List 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 one = new ArrayList<>(); - final List 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 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 predicate = o -> o instanceof String; - final List 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 empty = Collections.emptyList(); + assertTrue(ListUtils.intersection(empty, fullList).isEmpty(), "result not empty"); } @Test @@ -180,158 +228,6 @@ public class ListUtilsTest { assertEquals(6, list.size()); } - @Test - public void testEmptyIfNull() { - assertTrue(ListUtils.emptyIfNull(null).isEmpty()); - - final List list = new ArrayList<>(); - assertSame(list, ListUtils.emptyIfNull(list)); - } - - @Test - public void testDefaultIfNull() { - assertTrue(ListUtils.defaultIfNull(null, Collections.emptyList()).isEmpty()); - - final List list = new ArrayList<>(); - assertSame(list, ListUtils.defaultIfNull(list, Collections.emptyList())); - } - - @Test - public void testEquals() { - final Collection data = Arrays.asList("a", "b", "c"); - - final List a = new ArrayList<>( data ); - final List 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 data = Arrays.asList("a", "b", "c"); - - final List a = new ArrayList<>(data); - final List 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 sub = new ArrayList<>(); - sub.add(a); - sub.add(b); - sub.add(x); - - final List 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 sub = new ArrayList<>(); - sub.add(a); - sub.add(b); - sub.add(x); - - final List 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 list = new ArrayList<>(); - list.add(a); - list.add(b); - list.add(a); - list.add(x); - - final List sub = new ArrayList<>(); - sub.add(a); - - final List result = ListUtils.subtract(list, sub); - assertEquals(3, result.size()); - - final List 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 list = new ArrayList<>(); - list.add(a); - list.add(null); - list.add(null); - list.add(x); - - final List sub = new ArrayList<>(); - sub.add(null); - - final List result = ListUtils.subtract(list, sub); - assertEquals(3, result.size()); - - final List 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 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 EQUALS_TWO = input -> input.intValue() == 2; + @Test + public void testPredicatedList() { + final Predicate predicate = o -> o instanceof String; + final List 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 sub = new ArrayList<>(); + sub.add(a); + sub.add(b); + sub.add(x); + + final List 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 sub = new ArrayList<>(); + sub.add(a); + sub.add(b); + sub.add(x); + + final List 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 list = new ArrayList<>(); + list.add(a); + list.add(b); + list.add(a); + list.add(x); + + final List sub = new ArrayList<>(); + sub.add(a); + + final List result = ListUtils.subtract(list, sub); + assertEquals(3, result.size()); + + final List 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 list = new ArrayList<>(); + list.add(a); + list.add(null); + list.add(null); + list.add(x); + + final List sub = new ArrayList<>(); + sub.add(null); + + final List result = ListUtils.subtract(list, sub); + assertEquals(3, result.size()); + + final List expected = new ArrayList<>(); + expected.add(a); + expected.add(null); + expected.add(x); + + assertEquals(expected, result); + } }