Add T ArrayUtils.arraycopy(T, int, int, int, Function) fluent style

Add T ArrayUtils.arraycopy(T, int, int, int, Supplier) fluent style
This commit is contained in:
Gary Gregory 2024-04-02 14:41:18 -04:00
parent 88374a270b
commit 8ddebc231e
4 changed files with 61 additions and 37 deletions

View File

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

View File

@ -29,6 +29,7 @@
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 @@ private static Object add(final Object array, final int index, final Object elem
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 static <T> T[] addAll(final T[] array1, @SuppressWarnings("unchecked") fi
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 static <T> T arraycopy(final T source, final int sourcePos, final T dest,
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 static int[] subarray(final int[] array, int startIndexInclusive, int end
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 static long[] subarray(final long[] array, int startIndexInclusive, int e
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 static short[] subarray(final short[] array, int startIndexInclusive, int
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 static <T> T[] subarray(final T[] array, int startIndexInclusive, int end
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));
}
/**

View File

@ -568,25 +568,23 @@ public static Set<Method> getOverrideHierarchy(final Method method, final Interf
* @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

View File

@ -1832,9 +1832,7 @@ public boolean endsWith(final String str) {
*/
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 String midString(int index, final int length) {
*/
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 char[] toCharArray() {
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 char[] toCharArray(final int startIndex, int endIndex) {
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);
}
/**