From a6df7f74564b9432bf38fe33c4adc0bc529bf7c9 Mon Sep 17 00:00:00 2001 From: Gary Gregory Date: Fri, 13 Aug 2021 23:09:01 -0400 Subject: [PATCH] Add and use ArrayUtils.setAll(T[], IntFunction). Add and use ArrayUtils.setAll(T[], Supplier). --- src/changes/changes.xml | 2 + .../org/apache/commons/lang3/ArrayUtils.java | 217 ++++++++++-------- .../org/apache/commons/lang3/CharUtils.java | 6 +- .../commons/lang3/ArrayUtilsSetTest.java | 61 +++++ 4 files changed, 180 insertions(+), 106 deletions(-) create mode 100644 src/test/java/org/apache/commons/lang3/ArrayUtilsSetTest.java diff --git a/src/changes/changes.xml b/src/changes/changes.xml index b4c4fda17..c8556a292 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -64,6 +64,8 @@ The type attribute can be add,update,fix,remove. Add and use null-safe Streams.of(T...). Add ClassUtils.comparator(). Add and use ThreadUtils.sleepQuietly(long). + Add and use ArrayUtils.setAll(T[], IntFunction). + Add and use ArrayUtils.setAll(T[], Supplier). Bump spotbugs-maven-plugin from 4.2.0 to 4.2.3 #735. Bump Bump actions/cache from v2.1.4 to v2.1.6 #742, #752, #764. diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java index c325b5846..fb66168c2 100644 --- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java +++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java @@ -27,6 +27,8 @@ import java.util.HashMap; import java.util.Map; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.IntFunction; +import java.util.function.Supplier; import org.apache.commons.lang3.builder.EqualsBuilder; import org.apache.commons.lang3.builder.HashCodeBuilder; @@ -708,7 +710,6 @@ public class ArrayUtils { return newArray; } - /** *

Inserts the specified element at the specified position in the array. * Shifts the element currently at that position (if any) and any subsequent @@ -754,6 +755,7 @@ public class ArrayUtils { return (T[]) add(array, index, element, clss); } + /** *

Copies the given array and adds the given element at the end of the new array. * @@ -2554,50 +2556,50 @@ public class ArrayUtils { return indexOf(array, valueToFind, 0); } - /** - *

Finds the index of the given value in the array starting at the given index. - * - *

This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array. - * - *

A negative startIndex is treated as zero. A startIndex larger than the array - * length will return {@link #INDEX_NOT_FOUND} ({@code -1}). - * - * @param array the array to search through for the object, may be {@code null} - * @param valueToFind the value to find - * @param startIndex the index to start searching at - * @return the index of the value within the array, - * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input - */ -public static int indexOf(final int[] array, final int valueToFind, int startIndex) { - if (array == null) { - return INDEX_NOT_FOUND; - } - if (startIndex < 0) { - startIndex = 0; - } - for (int i = startIndex; i < array.length; i++) { - if (valueToFind == array[i]) { - return i; - } - } - return INDEX_NOT_FOUND; -} - - // long IndexOf /** - *

Finds the index of the given value in the array. + *

Finds the index of the given value in the array starting at the given index. * *

This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array. * + *

A negative startIndex is treated as zero. A startIndex larger than the array + * length will return {@link #INDEX_NOT_FOUND} ({@code -1}). + * * @param array the array to search through for the object, may be {@code null} * @param valueToFind the value to find + * @param startIndex the index to start searching at * @return the index of the value within the array, * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input */ - public static int indexOf(final long[] array, final long valueToFind) { - return indexOf(array, valueToFind, 0); + public static int indexOf(final int[] array, final int valueToFind, int startIndex) { + if (array == null) { + return INDEX_NOT_FOUND; + } + if (startIndex < 0) { + startIndex = 0; + } + for (int i = startIndex; i < array.length; i++) { + if (valueToFind == array[i]) { + return i; + } + } + return INDEX_NOT_FOUND; } + // long IndexOf +/** + *

Finds the index of the given value in the array. + * + *

This method returns {@link #INDEX_NOT_FOUND} ({@code -1}) for a {@code null} input array. + * + * @param array the array to search through for the object, may be {@code null} + * @param valueToFind the value to find + * @return the index of the value within the array, + * {@link #INDEX_NOT_FOUND} ({@code -1}) if not found or {@code null} array input + */ +public static int indexOf(final long[] array, final long valueToFind) { + return indexOf(array, valueToFind, 0); +} + /** *

Finds the index of the given value in the array starting at the given index. * @@ -3154,9 +3156,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array) == 0; } - // IndexOf search - // ---------------------------------------------------------------------- - /** *

Checks if an array of primitive chars is empty or {@code null}. * @@ -3168,6 +3167,9 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array) == 0; } + // IndexOf search + // ---------------------------------------------------------------------- + /** *

Checks if an array of primitive doubles is empty or {@code null}. * @@ -3201,8 +3203,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array) == 0; } - - /** *

Checks if an array of primitive longs is empty or {@code null}. * @@ -3214,6 +3214,8 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array) == 0; } + + // ---------------------------------------------------------------------- /** *

Checks if an array of Objects is empty or {@code null}. @@ -3462,7 +3464,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array1) == getLength(array2); } - /** *

Checks whether two arrays are the same length, treating * {@code null} arrays as length {@code 0}. @@ -3478,6 +3479,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return getLength(array1) == getLength(array2); } + /** *

Checks whether two arrays are the same length, treating * {@code null} arrays as length {@code 0}. @@ -3992,7 +3994,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return lastIndexOf(array, valueToFind, Integer.MAX_VALUE); } - /** *

Finds the last index of the given value in the array starting at the given index. * @@ -4022,6 +4023,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return INDEX_NOT_FOUND; } + /** *

Finds the last index of the given value within the array. * @@ -4477,9 +4479,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return array; } - // Primitive/Object array converters - // ---------------------------------------------------------------------- - /** *

Defensive programming technique to change a {@code null} * reference to an empty one. @@ -4500,6 +4499,9 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return array; } + // Primitive/Object array converters + // ---------------------------------------------------------------------- + /** *

Defensive programming technique to change a {@code null} * reference to an empty one. @@ -6923,6 +6925,50 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd } } + /** + * Sets all elements of the specified array, using the provided generator supplier to compute each element. + * + *

+ * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate + * state. + *

+ * + * @param type of elements of the array. + * @param array array to be initialized. + * @param generator a function accepting an index and producing the desired value for that position. + * @return the input array + * @since 3.13.0 + */ + public static T[] setAll(T[] array, IntFunction generator) { + if (array != null && generator != null) { + Arrays.setAll(array, generator); + } + return array; + } + + /** + * Sets all elements of the specified array, using the provided generator supplier to compute each element. + * + *

+ * If the generator supplier throws an exception, it is relayed to the caller and the array is left in an indeterminate + * state. + *

+ * + * @param type of elements of the array. + * @param array array to be initialized. + * @param generator a function accepting an index and producing the desired value for that position. + * @return the input array + * @since 3.13.0 + */ + public static T[] setAll(T[] array, final Supplier generator) { + if (array != null && generator != null) { + for (int i = 0; i < array.length; i++) { + array[i] = generator.get(); + } + } + return array; + } + /** * Shifts the order of the given boolean array. * @@ -8231,6 +8277,7 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd swap(array, offset1, offset2, 1); } + /** * Swaps a series of elements in the given boolean array. * @@ -8273,7 +8320,6 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd } } - /** * Swaps two elements in the given byte array. * @@ -8936,9 +8982,9 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd } /** - *

Converts an array of primitive booleans to objects. + * Converts an array of primitive booleans to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code boolean} array * @return a {@code Boolean} array, {@code null} if null array input @@ -8951,16 +8997,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd return EMPTY_BOOLEAN_OBJECT_ARRAY; } final Boolean[] result = new Boolean[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE); - } - return result; + return setAll(result, i -> array[i] ? Boolean.TRUE : Boolean.FALSE); } /** - *

Converts an array of primitive bytes to objects. + * Converts an array of primitive bytes to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code byte} array * @return a {@code Byte} array, {@code null} if null array input @@ -8972,17 +9015,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_BYTE_OBJECT_ARRAY; } - final Byte[] result = new Byte[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Byte.valueOf(array[i]); - } - return result; + return setAll(new Byte[array.length], i -> Byte.valueOf(array[i])); } /** - *

Converts an array of primitive chars to objects. + * Converts an array of primitive chars to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code char} array * @return a {@code Character} array, {@code null} if null array input @@ -8994,17 +9033,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_CHARACTER_OBJECT_ARRAY; } - final Character[] result = new Character[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Character.valueOf(array[i]); - } - return result; + return setAll(new Character[array.length], i -> Character.valueOf(array[i])); } /** - *

Converts an array of primitive doubles to objects. + * Converts an array of primitive doubles to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code double} array * @return a {@code Double} array, {@code null} if null array input @@ -9016,17 +9051,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_DOUBLE_OBJECT_ARRAY; } - final Double[] result = new Double[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Double.valueOf(array[i]); - } - return result; + return setAll(new Double[array.length], i -> Double.valueOf(array[i])); } /** - *

Converts an array of primitive floats to objects. + * Converts an array of primitive floats to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code float} array * @return a {@code Float} array, {@code null} if null array input @@ -9038,17 +9069,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_FLOAT_OBJECT_ARRAY; } - final Float[] result = new Float[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Float.valueOf(array[i]); - } - return result; + return setAll(new Float[array.length], i -> Float.valueOf(array[i])); } /** - *

Converts an array of primitive ints to objects. + * Converts an array of primitive ints to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array an {@code int} array * @return an {@code Integer} array, {@code null} if null array input @@ -9060,17 +9087,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_INTEGER_OBJECT_ARRAY; } - final Integer[] result = new Integer[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Integer.valueOf(array[i]); - } - return result; + return setAll(new Integer[array.length], i -> Integer.valueOf(array[i])); } /** - *

Converts an array of primitive longs to objects. + * Converts an array of primitive longs to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code long} array * @return a {@code Long} array, {@code null} if null array input @@ -9082,17 +9105,13 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_LONG_OBJECT_ARRAY; } - final Long[] result = new Long[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Long.valueOf(array[i]); - } - return result; + return setAll(new Long[array.length], i -> Long.valueOf(array[i])); } /** - *

Converts an array of primitive shorts to objects. + * Converts an array of primitive shorts to objects. * - *

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

This method returns {@code null} for a {@code null} input array.

* * @param array a {@code short} array * @return a {@code Short} array, {@code null} if null array input @@ -9104,15 +9123,9 @@ public static int indexOf(final int[] array, final int valueToFind, int startInd if (array.length == 0) { return EMPTY_SHORT_OBJECT_ARRAY; } - final Short[] result = new Short[array.length]; - for (int i = 0; i < array.length; i++) { - result[i] = Short.valueOf(array[i]); - } - return result; + return setAll(new Short[array.length], i -> Short.valueOf(array[i])); } - // Boolean array converters - // ---------------------------------------------------------------------- /** *

Converts an array of object Booleans to primitives. * diff --git a/src/main/java/org/apache/commons/lang3/CharUtils.java b/src/main/java/org/apache/commons/lang3/CharUtils.java index 7ff7d249d..c533113df 100644 --- a/src/main/java/org/apache/commons/lang3/CharUtils.java +++ b/src/main/java/org/apache/commons/lang3/CharUtils.java @@ -58,9 +58,7 @@ public class CharUtils { public static final char NUL = '\0'; static { - for (char c = 0; c < CHAR_STRING_ARRAY.length; c++) { - CHAR_STRING_ARRAY[c] = String.valueOf(c); - } + ArrayUtils.setAll(CHAR_STRING_ARRAY, i -> String.valueOf((char) i)); } /** @@ -302,7 +300,7 @@ public class CharUtils { * @return a String containing the one specified character */ public static String toString(final char ch) { - if (ch < 128) { + if (ch < CHAR_STRING_ARRAY.length) { return CHAR_STRING_ARRAY[ch]; } return new String(new char[] {ch}); diff --git a/src/test/java/org/apache/commons/lang3/ArrayUtilsSetTest.java b/src/test/java/org/apache/commons/lang3/ArrayUtilsSetTest.java new file mode 100644 index 000000000..41b1b9b3c --- /dev/null +++ b/src/test/java/org/apache/commons/lang3/ArrayUtilsSetTest.java @@ -0,0 +1,61 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.commons.lang3; + +import static org.junit.jupiter.api.Assertions.assertArrayEquals; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertSame; + +import java.util.function.IntFunction; +import java.util.function.Supplier; + +import org.junit.jupiter.api.Test; + +public class ArrayUtilsSetTest { + + @Test + public void testSetAll_IntFunction() { + final IntFunction nullIntFunction = null; + assertNull(ArrayUtils.setAll(null, nullIntFunction)); + assertArrayEquals(null, ArrayUtils.setAll(null, nullIntFunction)); + assertArrayEquals(ArrayUtils.EMPTY_BOOLEAN_OBJECT_ARRAY, ArrayUtils.setAll(ArrayUtils.EMPTY_BOOLEAN_OBJECT_ARRAY, nullIntFunction)); + assertArrayEquals(ArrayUtils.EMPTY_OBJECT_ARRAY, ArrayUtils.setAll(ArrayUtils.EMPTY_OBJECT_ARRAY, nullIntFunction)); + Integer[] array = new Integer[10]; + final Integer[] array2 = ArrayUtils.setAll(array, Integer::valueOf); + assertSame(array, array2); + for (int i = 0; i < array.length; i++) { + assertEquals(i, array[i].intValue()); + } + } + + @Test + public void testSetAll_Suppiler() { + final Supplier nullSupplier = null; + assertNull(ArrayUtils.setAll(null, nullSupplier)); + assertArrayEquals(null, ArrayUtils.setAll(null, nullSupplier)); + assertArrayEquals(ArrayUtils.EMPTY_BOOLEAN_OBJECT_ARRAY, ArrayUtils.setAll(ArrayUtils.EMPTY_BOOLEAN_OBJECT_ARRAY, nullSupplier)); + assertArrayEquals(ArrayUtils.EMPTY_OBJECT_ARRAY, ArrayUtils.setAll(ArrayUtils.EMPTY_OBJECT_ARRAY, nullSupplier)); + String[] array = new String[10]; + final String[] array2 = ArrayUtils.setAll(array, () -> StringUtils.EMPTY); + assertSame(array, array2); + for (String s : array) { + assertEquals(StringUtils.EMPTY, s); + } + } +}