commons-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From mben...@apache.org
Subject svn commit: r1147507 [1/2] - in /commons/proper/lang/trunk/src: main/java/org/apache/commons/lang3/ArrayUtils.java test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java
Date Sun, 17 Jul 2011 00:30:05 GMT
Author: mbenson
Date: Sun Jul 17 00:30:04 2011
New Revision: 1147507

URL: http://svn.apache.org/viewvc?rev=1147507&view=rev
Log:
[LANG-721] Complement ArrayUtils.addAll() variants with by-index and by-value removal methods

Added:
    commons/proper/lang/trunk/src/test/java/org/apache/commons/lang3/ArrayUtilsRemoveMultipleTest.java
  (with props)
Modified:
    commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ArrayUtils.java

Modified: commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ArrayUtils.java
URL: http://svn.apache.org/viewvc/commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ArrayUtils.java?rev=1147507&r1=1147506&r2=1147507&view=diff
==============================================================================
--- commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ArrayUtils.java (original)
+++ commons/proper/lang/trunk/src/main/java/org/apache/commons/lang3/ArrayUtils.java Sun Jul
17 00:30:04 2011
@@ -17,13 +17,16 @@
 package org.apache.commons.lang3;
 
 import java.lang.reflect.Array;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
 
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
 import org.apache.commons.lang3.builder.ToStringBuilder;
 import org.apache.commons.lang3.builder.ToStringStyle;
+import org.apache.commons.lang3.mutable.MutableInt;
 
 /**
  * <p>Operations on arrays, primitive arrays (like {@code int[]}) and
@@ -4932,4 +4935,855 @@ public class ArrayUtils {
         return result;
     }
 
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll(["a", "b", "c"], 0, 2) = ["b"]
+     * ArrayUtils.removeAll(["a", "b", "c"], 1, 2) = ["a"]
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    @SuppressWarnings("unchecked")
+    // removeAll() always creates an array of the same type as its input
+    public static <T> T[] removeAll(T[] array, int... indices) {
+        return (T[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, "a", "b")            = null
+     * ArrayUtils.removeElements([], "a", "b")              = []
+     * ArrayUtils.removeElements(["a"], "b", "c")           = ["a"]
+     * ArrayUtils.removeElements(["a", "b"], "a", "c")      = ["b"]
+     * ArrayUtils.removeElements(["a", "b", "a"], "a")      = ["b", "a"]
+     * ArrayUtils.removeElements(["a", "b", "a"], "a", "a") = ["b"]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static <T> T[] removeElements(T[] array, T... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<T, MutableInt> occurrences = new HashMap<T, MutableInt>(values.length);
+        for (T v : values) {
+            MutableInt count = occurrences.get(v);
+            if (count == null) {
+                occurrences.put(v, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<T, MutableInt> e : occurrences.entrySet()) {
+            T v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v, found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static byte[] removeAll(byte[] array, int... indices) {
+        return (byte[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static byte[] removeElements(byte[] array, byte... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Byte, MutableInt> occurrences = new HashMap<Byte, MutableInt>(values.length);
+        for (byte v : values) {
+            Byte boxed = Byte.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Byte, MutableInt> e : occurrences.entrySet()) {
+            Byte v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.byteValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static short[] removeAll(short[] array, int... indices) {
+        return (short[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static short[] removeElements(short[] array, short... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Short, MutableInt> occurrences = new HashMap<Short, MutableInt>(values.length);
+        for (short v : values) {
+            Short boxed = Short.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Short, MutableInt> e : occurrences.entrySet()) {
+            Short v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.shortValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static int[] removeAll(int[] array, int... indices) {
+        return (int[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static int[] removeElements(int[] array, int... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Integer, MutableInt> occurrences = new HashMap<Integer, MutableInt>(values.length);
+        for (int v : values) {
+            Integer boxed = Integer.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Integer, MutableInt> e : occurrences.entrySet()) {
+            Integer v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.intValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static char[] removeAll(char[] array, int... indices) {
+        return (char[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static char[] removeElements(char[] array, char... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Character, MutableInt> occurrences = new HashMap<Character, MutableInt>(values.length);
+        for (char v : values) {
+            Character boxed = Character.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Character, MutableInt> e : occurrences.entrySet()) {
+            Character v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.charValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static long[] removeAll(long[] array, int... indices) {
+        return (long[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static long[] removeElements(long[] array, long... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Long, MutableInt> occurrences = new HashMap<Long, MutableInt>(values.length);
+        for (long v : values) {
+            Long boxed = Long.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Long, MutableInt> e : occurrences.entrySet()) {
+            Long v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.longValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static float[] removeAll(float[] array, int... indices) {
+        return (float[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static float[] removeElements(float[] array, float... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Float, MutableInt> occurrences = new HashMap<Float, MutableInt>(values.length);
+        for (float v : values) {
+            Float boxed = Float.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Float, MutableInt> e : occurrences.entrySet()) {
+            Float v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.floatValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([1], 0)             = []
+     * ArrayUtils.removeAll([2, 6], 0)          = [6]
+     * ArrayUtils.removeAll([2, 6], 0, 1)       = []
+     * ArrayUtils.removeAll([2, 6, 3], 1, 2)    = [2]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 2)    = [6]
+     * ArrayUtils.removeAll([2, 6, 3], 0, 1, 2) = []
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static double[] removeAll(double[] array, int... indices) {
+        return (double[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, 1, 2)      = null
+     * ArrayUtils.removeElements([], 1, 2)        = []
+     * ArrayUtils.removeElements([1], 2, 3)       = [1]
+     * ArrayUtils.removeElements([1, 3], 1, 2)    = [3]
+     * ArrayUtils.removeElements([1, 3, 1], 1)    = [3, 1]
+     * ArrayUtils.removeElements([1, 3, 1], 1, 1) = [3]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static double[] removeElements(double[] array, double... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Double, MutableInt> occurrences = new HashMap<Double, MutableInt>(values.length);
+        for (double v : values) {
+            Double boxed = Double.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Double, MutableInt> e : occurrences.entrySet()) {
+            Double v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.doubleValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * <p>Removes the elements at the specified positions from the specified array.
+     * All remaining elements are shifted to the left.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except those at the specified positions. The component
+     * type of the returned array is always the same as that of the input
+     * array.</p>
+     *
+     * <p>If the input array is {@code null}, an IndexOutOfBoundsException
+     * will be thrown, because in that case no valid index can be specified.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeAll([true, false, true], 0, 2) = [false]
+     * ArrayUtils.removeAll([true, false, true], 1, 2) = [true]
+     * </pre>
+     *
+     * @param <T> the component type of the array
+     * @param array   the array to remove the element from, may not be {@code null}
+     * @param indices the positions of the elements to be removed
+     * @return A new array containing the existing elements except those
+     *         at the specified positions.
+     * @throws IndexOutOfBoundsException if any index is out of range
+     * (index < 0 || index >= array.length), or if the array is {@code null}.
+     * @since 3.0.1
+     */
+    public static boolean[] removeAll(boolean[] array, int... indices) {
+        return (boolean[]) removeAll((Object) array, clone(indices));
+    }
+
+    /**
+     * <p>Removes occurrences of specified elements, in specified quantities,
+     * from the specified array. All subsequent elements are shifted left.
+     * For any element-to-be-removed specified in greater quantities than
+     * contained in the original array, no change occurs beyond the
+     * removal of the existing matching items.</p>
+     *
+     * <p>This method returns a new array with the same elements of the input
+     * array except for the earliest-encountered occurrences of the specified
+     * elements. The component type of the returned array is always the same
+     * as that of the input array.</p>
+     *
+     * <pre>
+     * ArrayUtils.removeElements(null, true, false)               = null
+     * ArrayUtils.removeElements([], true, false)                 = []
+     * ArrayUtils.removeElements([true], false, false)            = [true]
+     * ArrayUtils.removeElements([true, false], true, true)       = [false]
+     * ArrayUtils.removeElements([true, false, true], true)       = [false, true]
+     * ArrayUtils.removeElements([true, false, true], true, true) = [false]
+     * </pre>
+     *
+     * @param array  the array to remove the element from, may be {@code null}
+     * @param elements  the elements to be removed
+     * @return A new array containing the existing elements except the
+     *         earliest-encountered occurrences of the specified elements.
+     * @since 3.0.1
+     */
+    public static boolean[] removeElements(boolean[] array, boolean... values) {
+        if (isEmpty(array) || isEmpty(values)) {
+            return clone(array);
+        }
+        HashMap<Boolean, MutableInt> occurrences = new HashMap<Boolean, MutableInt>(values.length);
+        for (boolean v : values) {
+            Boolean boxed = Boolean.valueOf(v);
+            MutableInt count = occurrences.get(boxed);
+            if (count == null) {
+                occurrences.put(boxed, new MutableInt(1));
+            } else {
+                count.increment();
+            }
+        }
+        HashSet<Integer> toRemove = new HashSet<Integer>();
+        for (Map.Entry<Boolean, MutableInt> e : occurrences.entrySet()) {
+            Boolean v = e.getKey();
+            int found = 0;
+            for (int i = 0, ct = e.getValue().intValue(); i < ct; i++) {
+                found = indexOf(array, v.booleanValue(), found);
+                if (found < 0) {
+                    break;
+                }
+                toRemove.add(found++);
+            }
+        }
+        return removeAll(array, toPrimitive(toRemove.toArray(new Integer[toRemove.size()])));
+    }
+
+    /**
+     * Removes multiple array elements specified by index.
+     * @param array source
+     * @param indices to remove, WILL BE SORTED--so only clones of user-owned arrays!
+     * @return new array of same type minus elements specified by unique values of {@code
indices}
+     * @since 3.0.1
+     */
+    private static Object removeAll(Object array, int... indices) {
+        int length = getLength(array);
+        int diff = 0;
+
+        if (isNotEmpty(indices)) {
+            Arrays.sort(indices);
+
+            int i = indices.length;
+            int prevIndex = length;
+            while (--i >= 0) {
+                int index = indices[i];
+                if (index < 0 || index >= length) {
+                    throw new IndexOutOfBoundsException("Index: " + index + ", Length: "
+ length);
+                }
+                if (index >= prevIndex) {
+                    continue;
+                }
+                diff++;
+                prevIndex = index;
+            }
+        }
+        Object result = Array.newInstance(array.getClass().getComponentType(), length - diff);
+        if (diff < length) {
+            int end = length;
+            int dest = length - diff;
+            for (int i = indices.length - 1; i >= 0; i--) {
+                int index = indices[i];
+                if (end - index > 1) {
+                    int cp = end - index - 1;
+                    dest -= cp;
+                    System.arraycopy(array, index + 1, result, dest, cp);
+                }
+                end = index;
+            }
+            if (end > 0) {
+                System.arraycopy(array, 0, result, 0, end);
+            }
+        }
+        return result;
+    }
+
 }



Mime
View raw message