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-lang.git
The following commit(s) were added to refs/heads/master by this push: new 7eda946 [LANG-170] Add ArrayUtils.addFirst() methods. 7eda946 is described below commit 7eda9463c1c650b38813321211561e315f12d1bc Author: Gary Gregory <gardgreg...@gmail.com> AuthorDate: Wed Jul 17 12:35:06 2019 -0400 [LANG-170] Add ArrayUtils.addFirst() methods. --- src/changes/changes.xml | 1 + .../java/org/apache/commons/lang3/ArrayUtils.java | 266 +++++++++++++++++++++ .../apache/commons/lang3/ArrayUtilsAddTest.java | 243 ++++++++++++++++--- 3 files changed, 477 insertions(+), 33 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 7c6b3a5..ee969fa 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -52,6 +52,7 @@ The <action> type attribute can be add,update,fix,remove. <action type="update" dev="ggregory">checkstyle.version 8.18 -> 8.20.</action> <action issue="LANG-1461" type="add" dev="ggregory">Add null-safe StringUtils APIs to wrap String#getBytes([Charset|String]).</action> <action issue="LANG-1467" type="add" dev="ggregory">Add zero arg constructor for org.apache.commons.lang3.NotImplementedException.</action> + <action issue="LANG-1470" type="add" dev="ggregory">Add ArrayUtils.addFirst() methods.</action> </release> <release version="3.9" date="2019-04-09" description="New features and bug fixes. Requires Java 8, supports Java 9, 10, 11"> diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java index e3ccb2a..51363ce 100644 --- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java +++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java @@ -5384,6 +5384,272 @@ public class ArrayUtils { } /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, true) = [true] + * ArrayUtils.add([true], false) = [false, true] + * ArrayUtils.add([true, false], true) = [true, true, false] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static boolean[] addFirst(final boolean[] array, final boolean element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static byte[] addFirst(final byte[] array, final byte element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, '1') = ['1'] + * ArrayUtils.add(['1'], '0') = ['0', '1'] + * ArrayUtils.add(['1', '0'], '1') = ['1', '1', '0'] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static char[] addFirst(final char[] array, final char element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static double[] addFirst(final double[] array, final double element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static float[] addFirst(final float[] array, final float element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static int[] addFirst(final int[] array, final int element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static long[] addFirst(final long[] array, final long element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first position. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element. + * </p> + * + * <pre> + * ArrayUtils.add(null, 1) = [1] + * ArrayUtils.add([1], 0) = [0, 1] + * ArrayUtils.add([1, 0], 1) = [1, 1, 0] + * </pre> + * + * @param array the array to "add" the element to, may be {@code null}. + * @param element the object to add. + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. + * @since 3.10 + */ + public static short[] addFirst(final short[] array, final short element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** + * Copies the given array and adds the given element at the beginning of the new array. + * + * <p> + * The new array contains the same elements of the input array plus the given element in the first positioaddFirstaddFirstaddFirstn. The + * component type of the new array is the same as that of the input array. + * </p> + * + * <p> + * If the input array is {@code null}, a new one element array is returned whose component type is the same as the + * element, unless the element itself is null, in which case the return type is Object[] + * </p> + * + * <pre> + * ArrayUtils.add(null, null) = IllegalArgumentException + * ArrayUtils.add(null, "a") = ["a"] + * ArrayUtils.add(["a"], null) = [null, "a"] + * ArrayUtils.add(["a"], "b") = ["b", "a"] + * ArrayUtils.add(["a", "b"], "c") = ["c", "a", "b"] + * </pre> + * + * @param <T> the component type of the array + * @param array the array to "add" the element to, may be {@code null} + * @param element the object to add, may be {@code null} + * @return A new array containing the existing elements plus the new element The returned array type will be that of + * the input array (unless null), in which case it will have the same type as the element. If both are null, + * an IllegalArgumentException is thrown + * @since 3.10 + * @throws IllegalArgumentException if both arguments are null + */ + public static <T> T[] addFirst(final T[] array, final T element) { + return array == null ? add(array, element) : insert(0, array, element); + } + + /** * <p>Copies the given array and adds the given element at the end of the new array. * * <p>The new array contains the same elements of the input diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsAddTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsAddTest.java index 2b61c0e..3030308 100644 --- a/src/test/java/org/apache/commons/lang3/ArrayUtilsAddTest.java +++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsAddTest.java @@ -32,15 +32,180 @@ import org.junit.jupiter.api.Test; public class ArrayUtilsAddTest { @Test - public void testJira567() { - Number[] n; - // Valid array construction - n = ArrayUtils.addAll(new Number[]{Integer.valueOf(1)}, new Long[]{Long.valueOf(2)}); - assertEquals(2, n.length); - assertEquals(Number.class, n.getClass().getComponentType()); - // Invalid - can't store Long in Integer array - assertThrows(IllegalArgumentException.class, - () -> ArrayUtils.addAll(new Integer[]{Integer.valueOf(1)}, new Long[]{Long.valueOf(2)})); + public void testAddFirstBoolean() { + boolean[] newArray; + newArray = ArrayUtils.addFirst(null, false); + assertArrayEquals(new boolean[]{false}, newArray); + assertEquals(Boolean.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(null, true); + assertArrayEquals(new boolean[]{true}, newArray); + assertEquals(Boolean.TYPE, newArray.getClass().getComponentType()); + final boolean[] array1 = new boolean[]{true, false, true}; + newArray = ArrayUtils.addFirst(array1, false); + assertArrayEquals(new boolean[]{false, true, false, true}, newArray); + assertEquals(Boolean.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstByte() { + byte[] newArray; + newArray = ArrayUtils.addFirst((byte[]) null, (byte) 0); + assertArrayEquals(new byte[]{0}, newArray); + assertEquals(Byte.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((byte[]) null, (byte) 1); + assertArrayEquals(new byte[]{1}, newArray); + assertEquals(Byte.TYPE, newArray.getClass().getComponentType()); + final byte[] array1 = new byte[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, (byte) 0); + assertArrayEquals(new byte[]{0, 1, 2, 3}, newArray); + assertEquals(Byte.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, (byte) 4); + assertArrayEquals(new byte[]{4, 1, 2, 3}, newArray); + assertEquals(Byte.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstChar() { + char[] newArray; + newArray = ArrayUtils.addFirst((char[]) null, (char) 0); + assertArrayEquals(new char[]{0}, newArray); + assertEquals(Character.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((char[]) null, (char) 1); + assertArrayEquals(new char[]{1}, newArray); + assertEquals(Character.TYPE, newArray.getClass().getComponentType()); + final char[] array1 = new char[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, (char) 0); + assertArrayEquals(new char[]{0, 1, 2, 3}, newArray); + assertEquals(Character.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, (char) 4); + assertArrayEquals(new char[]{4, 1, 2, 3}, newArray); + assertEquals(Character.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstDouble() { + double[] newArray; + newArray = ArrayUtils.addFirst((double[]) null, 0); + assertArrayEquals(new double[]{0}, newArray); + assertEquals(Double.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((double[]) null, 1); + assertArrayEquals(new double[]{1}, newArray); + assertEquals(Double.TYPE, newArray.getClass().getComponentType()); + final double[] array1 = new double[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, 0); + assertArrayEquals(new double[]{0, 1, 2, 3}, newArray); + assertEquals(Double.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, 4); + assertArrayEquals(new double[]{4, 1, 2, 3}, newArray); + assertEquals(Double.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstFloat() { + float[] newArray; + newArray = ArrayUtils.addFirst((float[]) null, 0); + assertArrayEquals(new float[]{0}, newArray); + assertEquals(Float.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((float[]) null, 1); + assertArrayEquals(new float[]{1}, newArray); + assertEquals(Float.TYPE, newArray.getClass().getComponentType()); + final float[] array1 = new float[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, 0); + assertArrayEquals(new float[]{0, 1, 2, 3}, newArray); + assertEquals(Float.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, 4); + assertArrayEquals(new float[]{4, 1, 2, 3}, newArray); + assertEquals(Float.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstInt() { + int[] newArray; + newArray = ArrayUtils.addFirst((int[]) null, 0); + assertArrayEquals(new int[]{0}, newArray); + assertEquals(Integer.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((int[]) null, 1); + assertArrayEquals(new int[]{1}, newArray); + assertEquals(Integer.TYPE, newArray.getClass().getComponentType()); + final int[] array1 = new int[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, 0); + assertArrayEquals(new int[]{0, 1, 2, 3}, newArray); + assertEquals(Integer.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, 4); + assertArrayEquals(new int[]{4, 1, 2, 3}, newArray); + assertEquals(Integer.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstLong() { + long[] newArray; + newArray = ArrayUtils.addFirst((long[]) null, 0); + assertArrayEquals(new long[]{0}, newArray); + assertEquals(Long.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((long[]) null, 1); + assertArrayEquals(new long[]{1}, newArray); + assertEquals(Long.TYPE, newArray.getClass().getComponentType()); + final long[] array1 = new long[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, 0); + assertArrayEquals(new long[]{0, 1, 2, 3}, newArray); + assertEquals(Long.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, 4); + assertArrayEquals(new long[]{4, 1, 2, 3}, newArray); + assertEquals(Long.TYPE, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstObject() { + Object[] newArray; + + //show that not casting is okay + newArray = ArrayUtils.add((Object[]) null, "a"); + assertArrayEquals(new String[]{"a"}, newArray); + assertArrayEquals(new Object[]{"a"}, newArray); + assertEquals(String.class, newArray.getClass().getComponentType()); + + //show that not casting to Object[] is okay and will assume String based on "a" + final String[] newStringArray = ArrayUtils.add(null, "a"); + assertArrayEquals(new String[]{"a"}, newStringArray); + assertArrayEquals(new Object[]{"a"}, newStringArray); + assertEquals(String.class, newStringArray.getClass().getComponentType()); + + final String[] stringArray1 = new String[] { "a", "b", "c" }; + newArray = ArrayUtils.addFirst(stringArray1, null); + assertArrayEquals(new String[] { null, "a", "b", "c" }, newArray); + assertEquals(String.class, newArray.getClass().getComponentType()); + + newArray = ArrayUtils.addFirst(stringArray1, "d"); + assertArrayEquals(new String[] { "d", "a", "b", "c" }, newArray); + assertEquals(String.class, newArray.getClass().getComponentType()); + + Number[] numberArray1 = new Number[] { Integer.valueOf(1), Double.valueOf(2) }; + newArray = ArrayUtils.addFirst(numberArray1, Float.valueOf(3)); + assertArrayEquals(new Number[] { Float.valueOf(3), Integer.valueOf(1), Double.valueOf(2) }, newArray); + assertEquals(Number.class, newArray.getClass().getComponentType()); + + numberArray1 = null; + newArray = ArrayUtils.addFirst(numberArray1, Float.valueOf(3)); + assertArrayEquals(new Float[] { Float.valueOf(3) }, newArray); + assertEquals(Float.class, newArray.getClass().getComponentType()); + } + + @Test + public void testAddFirstShort() { + short[] newArray; + newArray = ArrayUtils.addFirst((short[]) null, (short) 0); + assertArrayEquals(new short[]{0}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst((short[]) null, (short) 1); + assertArrayEquals(new short[]{1}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + final short[] array1 = new short[]{1, 2, 3}; + newArray = ArrayUtils.addFirst(array1, (short) 0); + assertArrayEquals(new short[]{0, 1, 2, 3}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.addFirst(array1, (short) 4); + assertArrayEquals(new short[]{4, 1, 2, 3}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); } @Test @@ -167,24 +332,6 @@ public class ArrayUtilsAddTest { } @Test - public void testAddObjectArrayShort() { - short[] newArray; - newArray = ArrayUtils.add((short[]) null, (short) 0); - assertArrayEquals(new short[]{0}, newArray); - assertEquals(Short.TYPE, newArray.getClass().getComponentType()); - newArray = ArrayUtils.add((short[]) null, (short) 1); - assertArrayEquals(new short[]{1}, newArray); - assertEquals(Short.TYPE, newArray.getClass().getComponentType()); - final short[] array1 = new short[]{1, 2, 3}; - newArray = ArrayUtils.add(array1, (short) 0); - assertArrayEquals(new short[]{1, 2, 3, 0}, newArray); - assertEquals(Short.TYPE, newArray.getClass().getComponentType()); - newArray = ArrayUtils.add(array1, (short) 4); - assertArrayEquals(new short[]{1, 2, 3, 4}, newArray); - assertEquals(Short.TYPE, newArray.getClass().getComponentType()); - } - - @Test public void testAddObjectArrayObject() { Object[] newArray; @@ -221,12 +368,21 @@ public class ArrayUtilsAddTest { } @Test - @SuppressWarnings("deprecation") - public void testLANG571() { - final String[] stringArray=null; - final String aString=null; - assertThrows(IllegalArgumentException.class, () -> ArrayUtils.add(stringArray, aString)); - assertThrows(IllegalArgumentException.class, () -> ArrayUtils.add(stringArray, 0, aString)); + public void testAddObjectArrayShort() { + short[] newArray; + newArray = ArrayUtils.add((short[]) null, (short) 0); + assertArrayEquals(new short[]{0}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.add((short[]) null, (short) 1); + assertArrayEquals(new short[]{1}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + final short[] array1 = new short[]{1, 2, 3}; + newArray = ArrayUtils.add(array1, (short) 0); + assertArrayEquals(new short[]{1, 2, 3, 0}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); + newArray = ArrayUtils.add(array1, (short) 4); + assertArrayEquals(new short[]{1, 2, 3, 4}, newArray); + assertEquals(Short.TYPE, newArray.getClass().getComponentType()); } @Test @@ -495,4 +651,25 @@ public class ArrayUtilsAddTest { assertEquals("Index: -1, Length: 2", e.getMessage()); } + @Test + public void testJira567() { + Number[] n; + // Valid array construction + n = ArrayUtils.addAll(new Number[]{Integer.valueOf(1)}, new Long[]{Long.valueOf(2)}); + assertEquals(2, n.length); + assertEquals(Number.class, n.getClass().getComponentType()); + // Invalid - can't store Long in Integer array + assertThrows(IllegalArgumentException.class, + () -> ArrayUtils.addAll(new Integer[]{Integer.valueOf(1)}, new Long[]{Long.valueOf(2)})); + } + + @Test + @SuppressWarnings("deprecation") + public void testLANG571() { + final String[] stringArray=null; + final String aString=null; + assertThrows(IllegalArgumentException.class, () -> ArrayUtils.add(stringArray, aString)); + assertThrows(IllegalArgumentException.class, () -> ArrayUtils.add(stringArray, 0, aString)); + } + }