[LANG-170] Add ArrayUtils.addFirst() methods.

This commit is contained in:
Gary Gregory 2019-07-17 12:35:06 -04:00
parent a929004b21
commit 7eda9463c1
3 changed files with 477 additions and 33 deletions

View File

@ -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">

View File

@ -5383,6 +5383,272 @@ public class ArrayUtils {
return newArray;
}
/**
* 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.
*

View File

@ -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
@ -166,24 +331,6 @@ public class ArrayUtilsAddTest {
assertEquals(Long.TYPE, newArray.getClass().getComponentType());
}
@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));
}
}