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
commit 8ddebc231eb63d4e00ba3c04d108f2569c521561 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Tue Apr 2 14:41:18 2024 -0400 Add T ArrayUtils.arraycopy(T, int, int, int, Function) fluent style Add T ArrayUtils.arraycopy(T, int, int, int, Supplier) fluent style --- src/changes/changes.xml | 2 + .../java/org/apache/commons/lang3/ArrayUtils.java | 70 +++++++++++++++------- .../apache/commons/lang3/reflect/MethodUtils.java | 12 ++-- .../org/apache/commons/lang3/text/StrBuilder.java | 14 ++--- 4 files changed, 61 insertions(+), 37 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 20cb0d73d..f1a362703 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -57,6 +57,8 @@ The <action> type attribute can be add,update,fix,remove. <action issue="LANG-1724" type="add" dev="ggregory" due-to="Gary Gregory">Add Streams.nonNull(T), non-varargs variant.</action> <action issue="LANG-1724" type="add" dev="ggregory" due-to="Gary Gregory">Add ArrayUtils.nullTo(T[], T[]).</action> <action issue="LANG-1724" type="add" dev="ggregory" due-to="Gary Gregory">Add T ArrayUtils.arraycopy(T, int, T, int, int) fluent style.</action> + <action issue="LANG-1724" type="add" dev="ggregory" due-to="Gary Gregory">Add T ArrayUtils.arraycopy(T, int, int, int, Function) fluent style.</action> + <action issue="LANG-1724" type="add" dev="ggregory" due-to="Gary Gregory">Add T ArrayUtils.arraycopy(T, int, int, int, Supplier) fluent style.</action> <!-- FIX --> <action type="fix" dev="ggregory" due-to="Miklós Karakó, Gary Gregory">Improve Javadoc in ExceptionUtils #1136.</action> <action type="fix" dev="ggregory" due-to="Saiharshith Karuneegar Ramesh, Gary Gregory">Fixed two non-deterministic tests in EnumUtilsTest.java #1131.</action> diff --git a/src/main/java/org/apache/commons/lang3/ArrayUtils.java b/src/main/java/org/apache/commons/lang3/ArrayUtils.java index 7faf9cc03..718c20ffb 100644 --- a/src/main/java/org/apache/commons/lang3/ArrayUtils.java +++ b/src/main/java/org/apache/commons/lang3/ArrayUtils.java @@ -29,6 +29,7 @@ import java.util.Map; import java.util.Objects; import java.util.Random; import java.util.concurrent.ThreadLocalRandom; +import java.util.function.Function; import java.util.function.IntFunction; import java.util.function.Supplier; @@ -659,8 +660,7 @@ public class ArrayUtils { if (index > length || index < 0) { throw new IndexOutOfBoundsException("Index: " + index + ", Length: " + length); } - final Object result = Array.newInstance(clazz, length + 1); - System.arraycopy(array, 0, result, 0, index); + final Object result = arraycopy(array, 0, 0, index, () -> Array.newInstance(clazz, length + 1)); Array.set(result, index, element); if (index < length) { System.arraycopy(array, index, result, index + 1, length - index); @@ -1114,21 +1114,18 @@ public class ArrayUtils { return clone(array1); } final Class<T> type1 = getComponentType(array1); - final T[] joinedArray = newInstance(type1, array1.length + array2.length); - System.arraycopy(array1, 0, joinedArray, 0, array1.length); + final T[] joinedArray = arraycopy(array1, 0, 0, array1.length, () -> newInstance(type1, array1.length + array2.length)); try { System.arraycopy(array2, 0, joinedArray, array1.length, array2.length); } catch (final ArrayStoreException ase) { // Check if problem was due to incompatible types /* - * We do this here, rather than before the copy because: - * - it would be a wasted check most of the time - * - safer, in case check turns out to be too strict + * We do this here, rather than before the copy because: - it would be a wasted check most of the time - safer, in case check turns out to be too + * strict */ final Class<?> type2 = array2.getClass().getComponentType(); if (!type1.isAssignableFrom(type2)) { - throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " - + type1.getName(), ase); + throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of " + type1.getName(), ase); } throw ase; // No, so rethrow original } @@ -1395,6 +1392,46 @@ public class ArrayUtils { return dest; } + /** + * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array. + * + * @param <T> the type. + * @param source the source array. + * @param sourcePos starting position in the source array. + * @param destPos starting position in the destination data. + * @param length the number of array elements to be copied. + * @param allocator allocates the array to populate and return. + * @return dest + * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. + * @throws ArrayStoreException if an element in the <code>src</code> array could not be stored into the <code>dest</code> array because of a type + * mismatch. + * @throws NullPointerException if either <code>src</code> or <code>dest</code> is <code>null</code>. + * @since 3.15.0 + */ + public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Function<Integer, T> allocator) { + return arraycopy(source, sourcePos, allocator.apply(length), destPos, length); + } + + /** + * A fluent version of {@link System#arraycopy(Object, int, Object, int, int)} that returns the destination array. + * + * @param <T> the type. + * @param source the source array. + * @param sourcePos starting position in the source array. + * @param destPos starting position in the destination data. + * @param length the number of array elements to be copied. + * @param allocator allocates the array to populate and return. + * @return dest + * @throws IndexOutOfBoundsException if copying would cause access of data outside array bounds. + * @throws ArrayStoreException if an element in the <code>src</code> array could not be stored into the <code>dest</code> array because of a type + * mismatch. + * @throws NullPointerException if either <code>src</code> or <code>dest</code> is <code>null</code>. + * @since 3.15.0 + */ + public static <T> T arraycopy(final T source, final int sourcePos, final int destPos, final int length, final Supplier<T> allocator) { + return arraycopy(source, sourcePos, allocator.get(), destPos, length); + } + /** * Clones an array or returns {@code null}. * <p> @@ -8163,9 +8200,7 @@ public class ArrayUtils { if (newSize <= 0) { return EMPTY_INT_ARRAY; } - - final int[] subarray = new int[newSize]; - return arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return arraycopy(array, startIndexInclusive, 0, newSize, int[]::new); } /** @@ -8203,9 +8238,7 @@ public class ArrayUtils { if (newSize <= 0) { return EMPTY_LONG_ARRAY; } - - final long[] subarray = new long[newSize]; - return arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return arraycopy(array, startIndexInclusive, 0, newSize, long[]::new); } /** @@ -8243,9 +8276,7 @@ public class ArrayUtils { if (newSize <= 0) { return EMPTY_SHORT_ARRAY; } - - final short[] subarray = new short[newSize]; - return arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return arraycopy(array, startIndexInclusive, 0, newSize, short[]::new); } /** @@ -8293,8 +8324,7 @@ public class ArrayUtils { if (newSize <= 0) { return newInstance(type, 0); } - final T[] subarray = newInstance(type, newSize); - return arraycopy(array, startIndexInclusive, subarray, 0, newSize); + return arraycopy(array, startIndexInclusive, 0, newSize, () -> newInstance(type, newSize)); } /** diff --git a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java index 4de2b1d7f..86215b468 100644 --- a/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java +++ b/src/main/java/org/apache/commons/lang3/reflect/MethodUtils.java @@ -568,25 +568,23 @@ public class MethodUtils { * @since 3.5 */ static Object[] getVarArgs(final Object[] args, final Class<?>[] methodParameterTypes) { - if (args.length == methodParameterTypes.length && (args[args.length - 1] == null || - args[args.length - 1].getClass().equals(methodParameterTypes[methodParameterTypes.length - 1]))) { + if (args.length == methodParameterTypes.length + && (args[args.length - 1] == null || args[args.length - 1].getClass().equals(methodParameterTypes[methodParameterTypes.length - 1]))) { // The args array is already in the canonical form for the method. return args; } // Construct a new array matching the method's declared parameter types. - final Object[] newArgs = new Object[methodParameterTypes.length]; - // Copy the normal (non-varargs) parameters - System.arraycopy(args, 0, newArgs, 0, methodParameterTypes.length - 1); + final Object[] newArgs = ArrayUtils.arraycopy(args, 0, 0, methodParameterTypes.length - 1, () -> new Object[methodParameterTypes.length]); // Construct a new array for the variadic parameters final Class<?> varArgComponentType = methodParameterTypes[methodParameterTypes.length - 1].getComponentType(); final int varArgLength = args.length - methodParameterTypes.length + 1; - Object varArgsArray = Array.newInstance(ClassUtils.primitiveToWrapper(varArgComponentType), varArgLength); // Copy the variadic arguments into the varargs array. - System.arraycopy(args, methodParameterTypes.length - 1, varArgsArray, 0, varArgLength); + Object varArgsArray = ArrayUtils.arraycopy(args, methodParameterTypes.length - 1, 0, varArgLength, + s -> Array.newInstance(ClassUtils.primitiveToWrapper(varArgComponentType), varArgLength)); if (varArgComponentType.isPrimitive()) { // unbox from wrapper type to primitive type diff --git a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java index cf53a7baf..e8a91f4ee 100644 --- a/src/main/java/org/apache/commons/lang3/text/StrBuilder.java +++ b/src/main/java/org/apache/commons/lang3/text/StrBuilder.java @@ -1832,9 +1832,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build */ public StrBuilder ensureCapacity(final int capacity) { if (capacity > buffer.length) { - final char[] old = buffer; - buffer = new char[capacity * 2]; - System.arraycopy(old, 0, buffer, 0, size); + buffer = ArrayUtils.arraycopy(buffer, 0, 0, size, () -> new char[capacity * 2]); } return this; } @@ -2468,9 +2466,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build */ public StrBuilder minimizeCapacity() { if (buffer.length > length()) { - final char[] old = buffer; - buffer = new char[length()]; - System.arraycopy(old, 0, buffer, 0, size); + buffer = ArrayUtils.arraycopy(buffer, 0, 0, size, () -> new char[length()]); } return this; } @@ -2937,8 +2933,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build if (size == 0) { return ArrayUtils.EMPTY_CHAR_ARRAY; } - final char[] chars = new char[size]; - return ArrayUtils.arraycopy(buffer, 0, chars, 0, size); + return ArrayUtils.arraycopy(buffer, 0, 0, size, char[]::new); } /** @@ -2957,8 +2952,7 @@ public class StrBuilder implements CharSequence, Appendable, Serializable, Build if (len == 0) { return ArrayUtils.EMPTY_CHAR_ARRAY; } - final char[] chars = new char[len]; - return ArrayUtils.arraycopy(buffer, startIndex, chars, 0, len); + return ArrayUtils.arraycopy(buffer, startIndex, 0, len, char[]::new); } /**