From e7aa83220c625d8735a1543ca993be496c406c51 Mon Sep 17 00:00:00 2001 From: Looly Date: Thu, 30 Mar 2023 01:44:41 +0800 Subject: [PATCH] fix Array --- .../java/cn/hutool/core/array/ArrayUtil.java | 198 +++++++++--------- .../cn/hutool/core/array/ArrayWrapper.java | 22 +- .../core/cache/CacheConcurrentTest.java | 1 + .../cn/hutool/core/util/ArrayUtilTest.java | 7 + 4 files changed, 113 insertions(+), 115 deletions(-) diff --git a/hutool-core/src/main/java/cn/hutool/core/array/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/array/ArrayUtil.java index f3c68e0db..dd3100d3d 100755 --- a/hutool-core/src/main/java/cn/hutool/core/array/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/array/ArrayUtil.java @@ -41,6 +41,38 @@ import java.util.stream.Collectors; */ public class ArrayUtil extends PrimitiveArrayUtil { + /** + * 转为数组,如果values为数组,返回,否则返回一个只有values一个元素的数组 + * + * @param 数组类型 + * @param values 元素值 + * @return 数组 + */ + public static A ofArray(final Object values) { + return ofArray(values, null); + } + + /** + * 转为数组,如果values为数组,返回,否则返回一个只有values一个元素的数组 + * + * @param 数组类型 + * @param values 元素值 + * @param elementType 数组元素类型,{@code null}表示使用values的类型 + * @return 数组 + */ + @SuppressWarnings("unchecked") + public static 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 /** @@ -172,6 +204,9 @@ public class ArrayUtil extends PrimitiveArrayUtil { */ @SuppressWarnings("unchecked") public static T firstNonNull(final T... array) { + if (isEmpty(array)) { + return null; + } return firstMatch(ObjUtil::isNotNull, array); } @@ -205,7 +240,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { */ @SuppressWarnings("unchecked") public static int matchIndex(final Predicate 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 */ @SuppressWarnings("unchecked") - public static int matchIndex(final Predicate matcher, final int beginIndexInclude, final T... array) { - if (isNotEmpty(array)) { - if (null == matcher && beginIndexInclude < array.length) { - return beginIndexInclude; - } - for (int i = beginIndexInclude; i < array.length; i++) { - if (matcher.test(array[i])) { - return i; - } - } + public static int matchIndex(final int beginIndexInclude, final Predicate matcher, final T... array) { + if (isEmpty(array)) { + return INDEX_NOT_FOUND; } - - return INDEX_NOT_FOUND; + return ArrayWrapper.of(array).matchIndex(beginIndexInclude, matcher); } /** @@ -274,7 +301,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @since 3.2.2 */ 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 public static A append(final A array, final T... newElements) { if (isEmpty(array)) { + if (null == array) { + return (A) newElements; + } // 可变长参数可能为包装类型,如果array是原始类型,则此处强转不合适,采用万能转换器完成转换 return (A) Convert.convert(array.getClass(), newElements); } @@ -379,25 +409,18 @@ public class ArrayUtil extends PrimitiveArrayUtil { /** * 将元素值设置为数组的某个位置,当给定的index大于等于数组长度,则追加 * - * @param 数组元素类型 - * @param buffer 已有数组 - * @param index 位置,大于等于长度则追加,否则替换 - * @param value 新值 + * @param 数组元素类型 + * @param array 已有数组 + * @param index 位置,大于等于长度则追加,否则替换 + * @param value 新值 * @return 新数组或原有数组 * @since 4.1.2 */ - public static T[] setOrAppend(final T[] buffer, final int index, final T value) { - if (index < buffer.length) { - Array.set(buffer, index, value); - 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); + public static T[] setOrAppend(final T[] array, final int index, final T value) { + if (isEmpty(array)) { + return ofArray(value, null == array ? null : array.getClass().getComponentType()); } + return ArrayWrapper.of(array).setOrAppend(index, value).getRaw(); } /** @@ -411,12 +434,10 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @since 4.1.2 */ public static A setOrAppend(final A array, final int index, final Object value) { - if (index < length(array)) { - Array.set(array, index, value); - return array; - } else { - return append(array, value); + if (isEmpty(array)) { + return ofArray(value, null == array ? null : array.getClass().getComponentType()); } + return ArrayWrapper.of(array).setOrAppend(index, value).getRaw(); } /** @@ -437,32 +458,33 @@ public class ArrayUtil extends PrimitiveArrayUtil { */ @SuppressWarnings({"unchecked"}) public static T[] replace(final T[] buffer, final int index, final T... values) { - if (isEmpty(values)) { - return buffer; - } if (isEmpty(buffer)) { return values; } - if (index < 0) { - // 从头部追加 - return insert(buffer, 0, values); - } - if (index >= buffer.length) { - // 超出长度,尾部追加 - return append(buffer, values); - } + return ArrayWrapper.of(buffer).replace(index, values).getRaw(); + } - if (buffer.length >= values.length + index) { - System.arraycopy(values, 0, buffer, index, values.length); - return buffer; + /** + * 从数组中的指定位置开始,按顺序使用新元素替换旧元素
+ *
    + *
  • 如果 指定位置 为负数,那么生成一个新数组,其中新元素按顺序放在数组头部
  • + *
  • 如果 指定位置 大于等于 旧数组长度,那么生成一个新数组,其中新元素按顺序放在数组尾部
  • + *
  • 如果 指定位置 加上 新元素数量 大于 旧数组长度,那么生成一个新数组,指定位置之前是旧数组元素,指定位置及之后为新元素
  • + *
  • 否则,从已有数组中的指定位置开始,按顺序使用新元素替换旧元素,返回旧数组
  • + *
+ * + * @param
数组类型 + * @param array 已有数组 + * @param index 位置 + * @param values 新值 + * @return 新数组或原有数组 + * @since 5.7.23 + */ + public static A replace(final A array, final int index, final Object values) { + if (isEmpty(array)) { + return ofArray(values, null == array ? null : array.getClass().getComponentType()); } - - // 替换长度大于原数组长度,新建数组 - 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; + return ArrayWrapper.of(array).replace(index, values).getRaw(); } /** @@ -495,36 +517,13 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @return 新数组 * @since 4.0.8 */ - @SuppressWarnings({"unchecked", "SuspiciousSystemArraycopy"}) - public static A insert(final A array, int index, final T... newElements) { - if (isEmpty(newElements)) { - 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; + @SafeVarargs + public static A insert(final A array, final int index, final T... newElements) { + return ArrayWrapper.of(array).insert(index, newElements).getRaw(); } + // region ----- resize + /** * 生成一个新的重新设置大小的数组
* 调整大小后,按顺序拷贝原数组到新数组中,新长度更小则截断
@@ -585,6 +584,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { public static T[] resize(final T[] buffer, final int newSize) { return resize(buffer, newSize, buffer.getClass().getComponentType()); } + // endregion /** * 合并所有数组,返回合并后的新数组
@@ -622,6 +622,8 @@ public class ArrayUtil extends PrimitiveArrayUtil { return result; } + // region ----- copy and clone + /** * 包装 {@link System#arraycopy(Object, int, Object, int, int)}
* 数组复制,源数组和目标数组都是从位置0开始复制,复制长度为源数组的长度
@@ -712,6 +714,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { } return null; } + // endregion /** * 对每个数组元素执行指定操作,返回操作后的元素
@@ -870,7 +873,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { * @since 3.0.7 */ public static 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 */ public static 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 值 * @since 4.0.6 */ - @SuppressWarnings("unchecked") - public static T get(final Object array, int 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); + public static T get(final Object array, final int index) { + return ArrayWrapper.of(array).get(index); } /** @@ -1287,10 +1279,10 @@ public class ArrayUtil extends PrimitiveArrayUtil { } return StrJoiner.of(delimiter, prefix, suffix) - // 每个元素都添加前后缀 - .setWrapElement(true) - .append(array) - .toString(); + // 每个元素都添加前后缀 + .setWrapElement(true) + .append(array) + .toString(); } /** @@ -2134,7 +2126,7 @@ public class ArrayUtil extends PrimitiveArrayUtil { if (array == prefix) { return true; } - if(isEmpty(array)){ + if (isEmpty(array)) { return isEmpty(prefix); } if (prefix.length > array.length) { diff --git a/hutool-core/src/main/java/cn/hutool/core/array/ArrayWrapper.java b/hutool-core/src/main/java/cn/hutool/core/array/ArrayWrapper.java index 835eb8043..fff3a3ce9 100755 --- a/hutool-core/src/main/java/cn/hutool/core/array/ArrayWrapper.java +++ b/hutool-core/src/main/java/cn/hutool/core/array/ArrayWrapper.java @@ -24,7 +24,7 @@ public class ArrayWrapper
implements Wrapper { private int length; /** - * 创建ArrayWrapper + * 创建ArrayWrapper,创建一个指定长度的空数组 * * @param componentType 元素类型 * @param length 长度 @@ -39,7 +39,7 @@ public class ArrayWrapper implements Wrapper { /** * 包装数组为ArrayWrapper * - * @param array 数组 + * @param array 数组(非空) * @param 数组类型 * @return ArrayWrapper */ @@ -50,11 +50,11 @@ public class ArrayWrapper implements Wrapper { /** * 构造 * - * @param array 数组对象 + * @param array 数组对象(非空) */ public ArrayWrapper(final A array) { - Assert.notNull(array); - if (ArrayUtil.isArray(array)) { + Assert.notNull(array, "Array must be not null!"); + if (false == ArrayUtil.isArray(array)) { throw new IllegalArgumentException("Object is not a array!"); } this.componentType = array.getClass().getComponentType(); @@ -302,9 +302,7 @@ public class ArrayWrapper implements Wrapper { public ArrayWrapper insert(int index, Object arrayToAppend) { if (false == ArrayUtil.isArray(arrayToAppend)) { // 用户传入单个元素则创建单元素数组 - if (arrayToAppend.getClass() == this.componentType) { - arrayToAppend = createSingleElementArray(arrayToAppend); - } + arrayToAppend = createSingleElementArray(arrayToAppend); } final int appendLength = ArrayUtil.length(arrayToAppend); @@ -313,6 +311,7 @@ public class ArrayWrapper implements Wrapper { } if (isEmpty()) { setNewArray((A) Convert.convert(array.getClass(), arrayToAppend)); + return this; } final int len = this.length; @@ -357,9 +356,7 @@ public class ArrayWrapper implements Wrapper { public ArrayWrapper replace(final int index, Object values) { if (false == ArrayUtil.isArray(values)) { // 用户传入单个元素则创建单元素数组 - if (values.getClass() == this.componentType) { - values = createSingleElementArray(values); - } + values = createSingleElementArray(values); } final int valuesLength = ArrayUtil.length(values); @@ -481,6 +478,7 @@ public class ArrayWrapper implements Wrapper { } // region ----- private methods + /** * 设置新数组,并更新长度 * @@ -500,7 +498,7 @@ public class ArrayWrapper implements Wrapper { private Object createSingleElementArray(final Object value) { // 插入单个元素 final Object newInstance = Array.newInstance(this.componentType, 1); - Array.set(newInstance, 1, value); + Array.set(newInstance, 0, value); return newInstance; } // endregion diff --git a/hutool-core/src/test/java/cn/hutool/core/cache/CacheConcurrentTest.java b/hutool-core/src/test/java/cn/hutool/core/cache/CacheConcurrentTest.java index ffd43f19e..75d6df3f7 100755 --- a/hutool-core/src/test/java/cn/hutool/core/cache/CacheConcurrentTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/cache/CacheConcurrentTest.java @@ -87,6 +87,7 @@ public class CacheConcurrentTest { } } + @SuppressWarnings("resource") @Test public void effectiveTest() { // 模拟耗时操作消耗时间 diff --git a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java index 7a5ed2dd9..8469769c1 100755 --- a/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java +++ b/hutool-core/src/test/java/cn/hutool/core/util/ArrayUtilTest.java @@ -517,6 +517,13 @@ public class ArrayUtilTest { 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 public void setOrAppendTest() { final String[] arr = new String[0];