diff --git a/src/changes/changes.xml b/src/changes/changes.xml index bae1160a7..a117f1d92 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -22,6 +22,7 @@ + Add ArrayUtils.reverse(array, from, to) methods. StringUtils.toString(byte[], String) deprecated in favour of a new StringUtils.toString(byte[], CharSet) RandomStringUtils.random javadoc was incorrectly promising letters and numbers would, as opposed to may, appear BooleanUtils.xor(boolean...) produces wrong results diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java index b3c728d41..202042b92 100644 --- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java +++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java @@ -1435,16 +1435,7 @@ public static void reverse(final Object[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - Object tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1458,16 +1449,7 @@ public static void reverse(final long[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - long tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1481,16 +1463,7 @@ public static void reverse(final int[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - int tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1504,16 +1477,7 @@ public static void reverse(final short[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - short tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1527,16 +1491,7 @@ public static void reverse(final char[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - char tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1550,16 +1505,7 @@ public static void reverse(final byte[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - byte tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1573,16 +1519,7 @@ public static void reverse(final double[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - double tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1596,16 +1533,7 @@ public static void reverse(final float[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; - float tmp; - while (j > i) { - tmp = array[j]; - array[j] = array[i]; - array[i] = tmp; - j--; - i++; - } + reverse(array, 0, array.length); } /** @@ -1619,8 +1547,33 @@ public static void reverse(final boolean[] array) { if (array == null) { return; } - int i = 0; - int j = array.length - 1; + reverse(array, 0, array.length); + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final boolean[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; boolean tmp; while (j > i) { tmp = array[j]; @@ -1631,6 +1584,278 @@ public static void reverse(final boolean[] array) { } } + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final byte[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + byte tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final char[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + char tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final double[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + double tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final float[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + float tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final int[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + int tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final long[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + long tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final Object[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + Object tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + + /** + *

+ * Reverses the order of the given array in the given range. + *

+ * + *

+ * This method does nothing for a {@code null} input array. + *

+ * + * @param array + * the array to reverse, may be {@code null} + * @param startIndexInclusive + * the starting index. Undervalue (<0) is promoted to 0, overvalue (>array.length) results in no + * change. + * @param endIndexExclusive + * elements up to endIndex-1 are reversed in the array. Undervalue (< start index) results in no + * change. Overvalue (>array.length) is demoted to array length. + */ + public static void reverse(final short[] array, int startIndexInclusive, int endIndexExclusive) { + if (array == null) { + return; + } + int i = startIndexInclusive < 0 ? 0 : startIndexInclusive; + int j = Math.min(array.length, endIndexExclusive) - 1; + short tmp; + while (j > i) { + tmp = array[j]; + array[j] = array[i]; + array[i] = tmp; + j--; + i++; + } + } + // IndexOf search // ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java index 9b9b0e9ea..cbe6ea783 100644 --- a/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsTest.java @@ -1806,6 +1806,295 @@ public void testReverseBoolean() { assertEquals(null, array); } + @Test + public void testReverseBooleanRange() { + boolean[] array = new boolean[] {false, false, true}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertTrue(array[0]); + assertFalse(array[1]); + assertFalse(array[2]); + // a range + array = new boolean[] {false, false, true}; + ArrayUtils.reverse(array, 0, 2); + assertFalse(array[0]); + assertFalse(array[1]); + assertTrue(array[2]); + // a range with a negative start + array = new boolean[] {false, false, true}; + ArrayUtils.reverse(array, -1, 3); + assertTrue(array[0]); + assertFalse(array[1]); + assertFalse(array[2]); + // a range with a large stop idnex + array = new boolean[] {false, false, true}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertTrue(array[0]); + assertFalse(array[1]); + assertFalse(array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseByteRange() { + byte[] array = new byte[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range + array = new byte[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0]); + assertEquals(1, array[1]); + assertEquals(3, array[2]); + // a range with a negative start + array = new byte[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range with a large stop idnex + array = new byte[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseCharRange() { + char[] array = new char[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range + array = new char[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0]); + assertEquals(1, array[1]); + assertEquals(3, array[2]); + // a range with a negative start + array = new char[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range with a large stop idnex + array = new char[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseDoubleRange() { + double[] array = new double[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // a range + array = new double[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0], 0); + assertEquals(1, array[1], 0); + assertEquals(3, array[2], 0); + // a range with a negative start + array = new double[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // a range with a large stop idnex + array = new double[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseFloatRange() { + float[] array = new float[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // a range + array = new float[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0], 0); + assertEquals(1, array[1], 0); + assertEquals(3, array[2], 0); + // a range with a negative start + array = new float[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // a range with a large stop idnex + array = new float[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0], 0); + assertEquals(2, array[1], 0); + assertEquals(1, array[2], 0); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseIntRange() { + int[] array = new int[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range + array = new int[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0]); + assertEquals(1, array[1]); + assertEquals(3, array[2]); + // a range with a negative start + array = new int[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range with a large stop idnex + array = new int[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseLongRange() { + long[] array = new long[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range + array = new long[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0]); + assertEquals(1, array[1]); + assertEquals(3, array[2]); + // a range with a negative start + array = new long[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range with a large stop idnex + array = new long[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseShortRange() { + short[] array = new short[] {1, 2, 3}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range + array = new short[] {1, 2, 3}; + ArrayUtils.reverse(array, 0, 2); + assertEquals(2, array[0]); + assertEquals(1, array[1]); + assertEquals(3, array[2]); + // a range with a negative start + array = new short[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, 3); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // a range with a large stop idnex + array = new short[] {1, 2, 3}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals(3, array[0]); + assertEquals(2, array[1]); + assertEquals(1, array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + @Test + public void testReverseObjectRange() { + String[] array = new String[] {"1", "2", "3"}; + // The whole array + ArrayUtils.reverse(array, 0, 3); + assertEquals("3", array[0]); + assertEquals("2", array[1]); + assertEquals("1", array[2]); + // a range + array = new String[] {"1", "2", "3"}; + ArrayUtils.reverse(array, 0, 2); + assertEquals("2", array[0]); + assertEquals("1", array[1]); + assertEquals("3", array[2]); + // a range with a negative start + array = new String[] {"1", "2", "3"}; + ArrayUtils.reverse(array, -1, 3); + assertEquals("3", array[0]); + assertEquals("2", array[1]); + assertEquals("1", array[2]); + // a range with a large stop idnex + array = new String[] {"1", "2", "3"}; + ArrayUtils.reverse(array, -1, array.length + 1000); + assertEquals("3", array[0]); + assertEquals("2", array[1]); + assertEquals("1", array[2]); + // null + array = null; + ArrayUtils.reverse(array, 0, 3); + assertEquals(null, array); + } + + //----------------------------------------------------------------------- @Test public void testIndexOf() {