fix Array

This commit is contained in:
Looly 2023-03-30 01:44:41 +08:00
parent 3ce7c3c36b
commit e7aa83220c
4 changed files with 113 additions and 115 deletions

View File

@ -41,6 +41,38 @@ import java.util.stream.Collectors;
*/ */
public class ArrayUtil extends PrimitiveArrayUtil { public class ArrayUtil extends PrimitiveArrayUtil {
/**
* 转为数组如果values为数组返回否则返回一个只有values一个元素的数组
*
* @param <A> 数组类型
* @param values 元素值
* @return 数组
*/
public static <A> A ofArray(final Object values) {
return ofArray(values, null);
}
/**
* 转为数组如果values为数组返回否则返回一个只有values一个元素的数组
*
* @param <A> 数组类型
* @param values 元素值
* @param elementType 数组元素类型{@code null}表示使用values的类型
* @return 数组
*/
@SuppressWarnings("unchecked")
public static <A> A ofArray(final Object values, final Class<?> elementType) {
if (isArray(values)) {
return (A) values;
}
// 插入单个元素
final Object newInstance = Array.newInstance(
null == elementType ? values.getClass() : elementType, 1);
Array.set(newInstance, 0, values);
return (A) newInstance;
}
// ---------------------------------------------------------------------- isEmpty // ---------------------------------------------------------------------- isEmpty
/** /**
@ -172,6 +204,9 @@ public class ArrayUtil extends PrimitiveArrayUtil {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> T firstNonNull(final T... array) { public static <T> T firstNonNull(final T... array) {
if (isEmpty(array)) {
return null;
}
return firstMatch(ObjUtil::isNotNull, array); return firstMatch(ObjUtil::isNotNull, array);
} }
@ -205,7 +240,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> int matchIndex(final Predicate<T> matcher, final T... array) { public static <T> int matchIndex(final Predicate<T> matcher, final T... array) {
return matchIndex(matcher, 0, array); return matchIndex(0, matcher, array);
} }
/** /**
@ -219,19 +254,11 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 5.7.3 * @since 5.7.3
*/ */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static <T> int matchIndex(final Predicate<T> matcher, final int beginIndexInclude, final T... array) { public static <T> int matchIndex(final int beginIndexInclude, final Predicate<T> matcher, final T... array) {
if (isNotEmpty(array)) { if (isEmpty(array)) {
if (null == matcher && beginIndexInclude < array.length) { return INDEX_NOT_FOUND;
return beginIndexInclude;
}
for (int i = beginIndexInclude; i < array.length; i++) {
if (matcher.test(array[i])) {
return i;
}
}
} }
return ArrayWrapper.of(array).matchIndex(beginIndexInclude, matcher);
return INDEX_NOT_FOUND;
} }
/** /**
@ -274,7 +301,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 3.2.2 * @since 3.2.2
*/ */
public static Class<?> getComponentType(final Object array) { public static Class<?> getComponentType(final Object array) {
return null == array ? null : array.getClass().getComponentType(); return null == array ? null : getComponentType(array.getClass());
} }
/** /**
@ -370,6 +397,9 @@ public class ArrayUtil extends PrimitiveArrayUtil {
@SafeVarargs @SafeVarargs
public static <A, T> A append(final A array, final T... newElements) { public static <A, T> A append(final A array, final T... newElements) {
if (isEmpty(array)) { if (isEmpty(array)) {
if (null == array) {
return (A) newElements;
}
// 可变长参数可能为包装类型如果array是原始类型则此处强转不合适采用万能转换器完成转换 // 可变长参数可能为包装类型如果array是原始类型则此处强转不合适采用万能转换器完成转换
return (A) Convert.convert(array.getClass(), newElements); return (A) Convert.convert(array.getClass(), newElements);
} }
@ -379,25 +409,18 @@ public class ArrayUtil extends PrimitiveArrayUtil {
/** /**
* 将元素值设置为数组的某个位置当给定的index大于等于数组长度则追加 * 将元素值设置为数组的某个位置当给定的index大于等于数组长度则追加
* *
* @param <T> 数组元素类型 * @param <T> 数组元素类型
* @param buffer 已有数组 * @param array 已有数组
* @param index 位置大于等于长度则追加否则替换 * @param index 位置大于等于长度则追加否则替换
* @param value 新值 * @param value 新值
* @return 新数组或原有数组 * @return 新数组或原有数组
* @since 4.1.2 * @since 4.1.2
*/ */
public static <T> T[] setOrAppend(final T[] buffer, final int index, final T value) { public static <T> T[] setOrAppend(final T[] array, final int index, final T value) {
if (index < buffer.length) { if (isEmpty(array)) {
Array.set(buffer, index, value); return ofArray(value, null == array ? null : array.getClass().getComponentType());
return buffer;
} else {
if (ArrayUtil.isEmpty(buffer)) {
final T[] values = newArray(value.getClass(), 1);
values[0] = value;
return append(buffer, values);
}
return append(buffer, value);
} }
return ArrayWrapper.of(array).setOrAppend(index, value).getRaw();
} }
/** /**
@ -411,12 +434,10 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 4.1.2 * @since 4.1.2
*/ */
public static <A> A setOrAppend(final A array, final int index, final Object value) { public static <A> A setOrAppend(final A array, final int index, final Object value) {
if (index < length(array)) { if (isEmpty(array)) {
Array.set(array, index, value); return ofArray(value, null == array ? null : array.getClass().getComponentType());
return array;
} else {
return append(array, value);
} }
return ArrayWrapper.of(array).setOrAppend(index, value).getRaw();
} }
/** /**
@ -437,32 +458,33 @@ public class ArrayUtil extends PrimitiveArrayUtil {
*/ */
@SuppressWarnings({"unchecked"}) @SuppressWarnings({"unchecked"})
public static <T> T[] replace(final T[] buffer, final int index, final T... values) { public static <T> T[] replace(final T[] buffer, final int index, final T... values) {
if (isEmpty(values)) {
return buffer;
}
if (isEmpty(buffer)) { if (isEmpty(buffer)) {
return values; return values;
} }
if (index < 0) { return ArrayWrapper.of(buffer).replace(index, values).getRaw();
// 从头部追加 }
return insert(buffer, 0, values);
}
if (index >= buffer.length) {
// 超出长度尾部追加
return append(buffer, values);
}
if (buffer.length >= values.length + index) { /**
System.arraycopy(values, 0, buffer, index, values.length); * 从数组中的指定位置开始按顺序使用新元素替换旧元素<br>
return buffer; * <ul>
* <li>如果 指定位置 为负数那么生成一个新数组其中新元素按顺序放在数组头部</li>
* <li>如果 指定位置 大于等于 旧数组长度那么生成一个新数组其中新元素按顺序放在数组尾部</li>
* <li>如果 指定位置 加上 新元素数量 大于 旧数组长度那么生成一个新数组指定位置之前是旧数组元素指定位置及之后为新元素</li>
* <li>否则从已有数组中的指定位置开始按顺序使用新元素替换旧元素返回旧数组</li>
* </ul>
*
* @param <A> 数组类型
* @param array 已有数组
* @param index 位置
* @param values 新值
* @return 新数组或原有数组
* @since 5.7.23
*/
public static <A> A replace(final A array, final int index, final Object values) {
if (isEmpty(array)) {
return ofArray(values, null == array ? null : array.getClass().getComponentType());
} }
return ArrayWrapper.of(array).replace(index, values).getRaw();
// 替换长度大于原数组长度新建数组
final int newArrayLength = index + values.length;
final T[] result = newArray(buffer.getClass().getComponentType(), newArrayLength);
System.arraycopy(buffer, 0, result, 0, index);
System.arraycopy(values, 0, result, index, values.length);
return result;
} }
/** /**
@ -495,36 +517,13 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @return 新数组 * @return 新数组
* @since 4.0.8 * @since 4.0.8
*/ */
@SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"}) @SafeVarargs
public static <A, T> A insert(final A array, int index, final T... newElements) { public static <A, T> A insert(final A array, final int index, final T... newElements) {
if (isEmpty(newElements)) { return ArrayWrapper.of(array).insert(index, newElements).getRaw();
return array;
}
if (isEmpty(array)) {
return (A) Convert.convert(array.getClass(), newElements);
}
final int len = length(array);
if (index < 0) {
index = (index % len) + len;
}
// 已有数组的元素类型
final Class<?> originComponentType = array.getClass().getComponentType();
Object newEleArr = newElements;
// 如果 已有数组的元素类型是 原始类型则需要转换 新元素数组 为该类型避免ArrayStoreException
if (originComponentType.isPrimitive()) {
newEleArr = Convert.convert(array.getClass(), newElements);
}
final Object result = Array.newInstance(originComponentType, Math.max(len, index) + newElements.length);
System.arraycopy(array, 0, result, 0, Math.min(len, index));
System.arraycopy(newEleArr, 0, result, index, newElements.length);
if (index < len) {
System.arraycopy(array, index, result, index + newElements.length, len - index);
}
return (A) result;
} }
// region ----- resize
/** /**
* 生成一个新的重新设置大小的数组<br> * 生成一个新的重新设置大小的数组<br>
* 调整大小后按顺序拷贝原数组到新数组中新长度更小则截断<br> * 调整大小后按顺序拷贝原数组到新数组中新长度更小则截断<br>
@ -585,6 +584,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
public static <T> T[] resize(final T[] buffer, final int newSize) { public static <T> T[] resize(final T[] buffer, final int newSize) {
return resize(buffer, newSize, buffer.getClass().getComponentType()); return resize(buffer, newSize, buffer.getClass().getComponentType());
} }
// endregion
/** /**
* 合并所有数组返回合并后的新数组<br> * 合并所有数组返回合并后的新数组<br>
@ -622,6 +622,8 @@ public class ArrayUtil extends PrimitiveArrayUtil {
return result; return result;
} }
// region ----- copy and clone
/** /**
* 包装 {@link System#arraycopy(Object, int, Object, int, int)}<br> * 包装 {@link System#arraycopy(Object, int, Object, int, int)}<br>
* 数组复制源数组和目标数组都是从位置0开始复制复制长度为源数组的长度<br> * 数组复制源数组和目标数组都是从位置0开始复制复制长度为源数组的长度<br>
@ -712,6 +714,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
} }
return null; return null;
} }
// endregion
/** /**
* 对每个数组元素执行指定操作返回操作后的元素<br> * 对每个数组元素执行指定操作返回操作后的元素<br>
@ -870,7 +873,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 3.0.7 * @since 3.0.7
*/ */
public static <T> int indexOf(final T[] array, final Object value, final int beginIndexInclude) { public static <T> int indexOf(final T[] array, final Object value, final int beginIndexInclude) {
return matchIndex((obj) -> ObjUtil.equals(value, obj), beginIndexInclude, array); return ArrayWrapper.of(array).indexOf(value, beginIndexInclude);
} }
/** /**
@ -883,7 +886,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @since 3.0.7 * @since 3.0.7
*/ */
public static <T> int indexOf(final T[] array, final Object value) { public static <T> int indexOf(final T[] array, final Object value) {
return matchIndex((obj) -> ObjUtil.equals(value, obj), array); return ArrayWrapper.of(array).indexOf(value);
} }
/** /**
@ -1067,19 +1070,8 @@ public class ArrayUtil extends PrimitiveArrayUtil {
* @return * @return
* @since 4.0.6 * @since 4.0.6
*/ */
@SuppressWarnings("unchecked") public static <T> T get(final Object array, final int index) {
public static <T> T get(final Object array, int index) { return ArrayWrapper.of(array).get(index);
if (null == array) {
return null;
}
final int length = Array.getLength(array);
if (index < 0) {
index += length;
}
if (index < 0 || index >= length) {
return null;
}
return (T) Array.get(array, index);
} }
/** /**
@ -1287,10 +1279,10 @@ public class ArrayUtil extends PrimitiveArrayUtil {
} }
return StrJoiner.of(delimiter, prefix, suffix) return StrJoiner.of(delimiter, prefix, suffix)
// 每个元素都添加前后缀 // 每个元素都添加前后缀
.setWrapElement(true) .setWrapElement(true)
.append(array) .append(array)
.toString(); .toString();
} }
/** /**
@ -2134,7 +2126,7 @@ public class ArrayUtil extends PrimitiveArrayUtil {
if (array == prefix) { if (array == prefix) {
return true; return true;
} }
if(isEmpty(array)){ if (isEmpty(array)) {
return isEmpty(prefix); return isEmpty(prefix);
} }
if (prefix.length > array.length) { if (prefix.length > array.length) {

View File

@ -24,7 +24,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
private int length; private int length;
/** /**
* 创建ArrayWrapper * 创建ArrayWrapper创建一个指定长度的空数组
* *
* @param componentType 元素类型 * @param componentType 元素类型
* @param length 长度 * @param length 长度
@ -39,7 +39,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
/** /**
* 包装数组为ArrayWrapper * 包装数组为ArrayWrapper
* *
* @param array 数组 * @param array 数组非空
* @param <A> 数组类型 * @param <A> 数组类型
* @return ArrayWrapper * @return ArrayWrapper
*/ */
@ -50,11 +50,11 @@ public class ArrayWrapper<A> implements Wrapper<A> {
/** /**
* 构造 * 构造
* *
* @param array 数组对象 * @param array 数组对象非空
*/ */
public ArrayWrapper(final A array) { public ArrayWrapper(final A array) {
Assert.notNull(array); Assert.notNull(array, "Array must be not null!");
if (ArrayUtil.isArray(array)) { if (false == ArrayUtil.isArray(array)) {
throw new IllegalArgumentException("Object is not a array!"); throw new IllegalArgumentException("Object is not a array!");
} }
this.componentType = array.getClass().getComponentType(); this.componentType = array.getClass().getComponentType();
@ -302,9 +302,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
public ArrayWrapper<A> insert(int index, Object arrayToAppend) { public ArrayWrapper<A> insert(int index, Object arrayToAppend) {
if (false == ArrayUtil.isArray(arrayToAppend)) { if (false == ArrayUtil.isArray(arrayToAppend)) {
// 用户传入单个元素则创建单元素数组 // 用户传入单个元素则创建单元素数组
if (arrayToAppend.getClass() == this.componentType) { arrayToAppend = createSingleElementArray(arrayToAppend);
arrayToAppend = createSingleElementArray(arrayToAppend);
}
} }
final int appendLength = ArrayUtil.length(arrayToAppend); final int appendLength = ArrayUtil.length(arrayToAppend);
@ -313,6 +311,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
} }
if (isEmpty()) { if (isEmpty()) {
setNewArray((A) Convert.convert(array.getClass(), arrayToAppend)); setNewArray((A) Convert.convert(array.getClass(), arrayToAppend));
return this;
} }
final int len = this.length; final int len = this.length;
@ -357,9 +356,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
public ArrayWrapper<A> replace(final int index, Object values) { public ArrayWrapper<A> replace(final int index, Object values) {
if (false == ArrayUtil.isArray(values)) { if (false == ArrayUtil.isArray(values)) {
// 用户传入单个元素则创建单元素数组 // 用户传入单个元素则创建单元素数组
if (values.getClass() == this.componentType) { values = createSingleElementArray(values);
values = createSingleElementArray(values);
}
} }
final int valuesLength = ArrayUtil.length(values); final int valuesLength = ArrayUtil.length(values);
@ -481,6 +478,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
} }
// region ----- private methods // region ----- private methods
/** /**
* 设置新数组并更新长度 * 设置新数组并更新长度
* *
@ -500,7 +498,7 @@ public class ArrayWrapper<A> implements Wrapper<A> {
private Object createSingleElementArray(final Object value) { private Object createSingleElementArray(final Object value) {
// 插入单个元素 // 插入单个元素
final Object newInstance = Array.newInstance(this.componentType, 1); final Object newInstance = Array.newInstance(this.componentType, 1);
Array.set(newInstance, 1, value); Array.set(newInstance, 0, value);
return newInstance; return newInstance;
} }
// endregion // endregion

View File

@ -87,6 +87,7 @@ public class CacheConcurrentTest {
} }
} }
@SuppressWarnings("resource")
@Test @Test
public void effectiveTest() { public void effectiveTest() {
// 模拟耗时操作消耗时间 // 模拟耗时操作消耗时间

View File

@ -517,6 +517,13 @@ public class ArrayUtilTest {
Assert.assertArrayEquals(g, result); Assert.assertArrayEquals(g, result);
} }
@Test
public void replaceTest2(){
int[] a = new int[0];
a = ArrayUtil.replace(a, 0, 1);
Assert.assertEquals(1, a.length);
}
@Test @Test
public void setOrAppendTest() { public void setOrAppendTest() {
final String[] arr = new String[0]; final String[] arr = new String[0];