diff --git a/CHANGELOG.md b/CHANGELOG.md index 4be421668..28c91769b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -17,6 +17,7 @@ * 【core 】 增加EnumItem接口,枚举扩展转换,增加SPI自定义转换(pr#173@Github) * 【core 】 TypeUtil增加getActualType,增加ActualTypeMapperPool类(issue#I1TBWH@Gitee) * 【extra 】 QRConfig中添加qrVersion属性(pr#1068@Github) +* 【core 】 ArrayUtil增加equals方法 ### Bug修复 * 【core 】 重新整理农历节假日,解决一个pr过来的玩笑导致的问题 diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/EqualsBuilder.java b/hutool-core/src/main/java/cn/hutool/core/builder/EqualsBuilder.java index 19a5299b1..5d6abf6d1 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/EqualsBuilder.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/EqualsBuilder.java @@ -39,6 +39,8 @@ import java.util.Set; * return EqualsBuilder.reflectionEquals(this, obj); * } * + * + * 来自Apache Commons Lang改造 */ public class EqualsBuilder implements Builder { private static final long serialVersionUID = 1L; @@ -47,8 +49,6 @@ public class EqualsBuilder implements Builder { *

* A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops. *

- * - * @since 3.0 */ private static final ThreadLocal>> REGISTRY = new ThreadLocal<>(); @@ -379,35 +379,13 @@ public class EqualsBuilder implements Builder { return this; } final Class lhsClass = lhs.getClass(); - if (!lhsClass.isArray()) { + if (false == lhsClass.isArray()) { // The simple case, not an array, just test the element isEquals = lhs.equals(rhs); - } else if (lhs.getClass() != rhs.getClass()) { - // Here when we compare different dimensions, for example: a boolean[][] to a boolean[] - this.setEquals(false); - } - // 'Switch' on type of array, to dispatch to the correct handler - // This handles multi dimensional arrays of the same depth - else if (lhs instanceof long[]) { - append((long[]) lhs, (long[]) rhs); - } else if (lhs instanceof int[]) { - append((int[]) lhs, (int[]) rhs); - } else if (lhs instanceof short[]) { - append((short[]) lhs, (short[]) rhs); - } else if (lhs instanceof char[]) { - append((char[]) lhs, (char[]) rhs); - } else if (lhs instanceof byte[]) { - append((byte[]) lhs, (byte[]) rhs); - } else if (lhs instanceof double[]) { - append((double[]) lhs, (double[]) rhs); - } else if (lhs instanceof float[]) { - append((float[]) lhs, (float[]) rhs); - } else if (lhs instanceof boolean[]) { - append((boolean[]) lhs, (boolean[]) rhs); - } else { - // Not an array of primitives - append((Object[]) lhs, (Object[]) rhs); } + + // 判断数组的equals + this.setEquals(ArrayUtil.equals(lhs, rhs)); return this; } @@ -543,285 +521,6 @@ public class EqualsBuilder implements Builder { return this; } - /** - *

Performs a deep comparison of two Object arrays.

- * - *

This also will be called for the top level of - * multi-dimensional, ragged, and multi-typed arrays.

- * - * @param lhs the left hand Object[] - * @param rhs the right hand Object[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final Object[] lhs, final Object[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of long. Length and all - * values are compared.

- * - *

The method {@link #append(long, long)} is used.

- * - * @param lhs the left hand long[] - * @param rhs the right hand long[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final long[] lhs, final long[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of int. Length and all - * values are compared.

- * - *

The method {@link #append(int, int)} is used.

- * - * @param lhs the left hand int[] - * @param rhs the right hand int[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final int[] lhs, final int[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of short. Length and all - * values are compared.

- * - *

The method {@link #append(short, short)} is used.

- * - * @param lhs the left hand short[] - * @param rhs the right hand short[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final short[] lhs, final short[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of char. Length and all - * values are compared.

- * - *

The method {@link #append(char, char)} is used.

- * - * @param lhs the left hand char[] - * @param rhs the right hand char[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final char[] lhs, final char[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of byte. Length and all - * values are compared.

- * - *

The method {@link #append(byte, byte)} is used.

- * - * @param lhs the left hand byte[] - * @param rhs the right hand byte[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final byte[] lhs, final byte[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of double. Length and all - * values are compared.

- * - *

The method {@link #append(double, double)} is used.

- * - * @param lhs the left hand double[] - * @param rhs the right hand double[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final double[] lhs, final double[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of float. Length and all - * values are compared.

- * - *

The method {@link #append(float, float)} is used.

- * - * @param lhs the left hand float[] - * @param rhs the right hand float[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final float[] lhs, final float[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - - /** - *

Deep comparison of array of boolean. Length and all - * values are compared.

- * - *

The method {@link #append(boolean, boolean)} is used.

- * - * @param lhs the left hand boolean[] - * @param rhs the right hand boolean[] - * @return EqualsBuilder - used to chain calls. - */ - public EqualsBuilder append(final boolean[] lhs, final boolean[] rhs) { - if (isEquals == false) { - return this; - } - if (lhs == rhs) { - return this; - } - if (lhs == null || rhs == null) { - this.setEquals(false); - return this; - } - if (lhs.length != rhs.length) { - this.setEquals(false); - return this; - } - for (int i = 0; i < lhs.length && isEquals; ++i) { - append(lhs[i], rhs[i]); - } - return this; - } - /** *

Returns true if the fields that have been checked * are all equal.

diff --git a/hutool-core/src/main/java/cn/hutool/core/builder/IDKey.java b/hutool-core/src/main/java/cn/hutool/core/builder/IDKey.java index af0c07fad..2100acc75 100644 --- a/hutool-core/src/main/java/cn/hutool/core/builder/IDKey.java +++ b/hutool-core/src/main/java/cn/hutool/core/builder/IDKey.java @@ -3,11 +3,10 @@ package cn.hutool.core.builder; import java.io.Serializable; /** - * Wrap an identity key (System.identityHashCode()) so that an object can only be equal() to itself. - * - * This is necessary to disambiguate the occasional duplicate identityHashCodes that can occur. - * - * TODO 待整理 + * 包装唯一键(System.identityHashCode())使对象只有和自己 equals + * + * 此对象用于消除小概率下System.identityHashCode()产生的ID重复问题。 + * * 来自于Apache-Commons-Lang3 * @author looly,Apache-Commons * @since 4.2.2 @@ -19,17 +18,16 @@ final class IDKey implements Serializable{ private final int id; /** - * Constructor for IDKey + * 构造 * - * @param _value The value + * @param obj 计算唯一ID的对象 */ - public IDKey(final Object _value) { - // This is the Object hashcode - id = System.identityHashCode(_value); + public IDKey(final Object obj) { + id = System.identityHashCode(obj); // There have been some cases (LANG-459) that return the // same identity hash code for different objects. So // the value is also added to disambiguate these cases. - value = _value; + value = obj; } /** diff --git a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java index 40c7e3bac..a16f40b78 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/ArrayUtil.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.CollectionUtil; import cn.hutool.core.collection.IterUtil; import cn.hutool.core.comparator.CompareUtil; import cn.hutool.core.exceptions.UtilException; +import cn.hutool.core.lang.Assert; import cn.hutool.core.lang.Editor; import cn.hutool.core.lang.Filter; import cn.hutool.core.lang.Matcher; @@ -4303,4 +4304,49 @@ public class ArrayUtil { } return result; } + + /** + * 判断两个数组是否相等,判断依据包括数组长度和每个元素都相等。 + * @param array1 数组1 + * @param array2 数组2 + * @return 是否相等 + * @since 5.4.2 + */ + public static boolean equals(Object array1, Object array2){ + if(array1 == array2){ + return true; + } + if(hasNull(array1, array2)){ + return false; + } + + Assert.isTrue(isArray(array1), "First is not a Array !"); + Assert.isTrue(isArray(array2), "Second is not a Array !"); + + // 数组类型一致性判断 + if(array1.getClass() != array2.getClass()){ + return false; + } + + if (array1 instanceof long[]) { + return Arrays.equals((long[]) array1, (long[]) array2); + } else if (array1 instanceof int[]) { + return Arrays.equals((int[]) array1, (int[]) array2); + } else if (array1 instanceof short[]) { + return Arrays.equals((short[]) array1, (short[]) array2); + } else if (array1 instanceof char[]) { + return Arrays.equals((char[]) array1, (char[]) array2); + } else if (array1 instanceof byte[]) { + return Arrays.equals((byte[]) array1, (byte[]) array2); + } else if (array1 instanceof double[]) { + return Arrays.equals((double[]) array1, (double[]) array2); + } else if (array1 instanceof float[]) { + return Arrays.equals((float[]) array1, (float[]) array2); + } else if (array1 instanceof boolean[]) { + return Arrays.equals((boolean[]) array1, (boolean[]) array2); + } else { + // Not an array of primitives + return Arrays.deepEquals((Object[]) array1, (Object[]) array2); + } + } } diff --git a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java index 3de02fa59..a674fd4df 100644 --- a/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java +++ b/hutool-core/src/main/java/cn/hutool/core/util/NumberUtil.java @@ -1712,8 +1712,13 @@ public class NumberUtil { * @return 是否相等 */ public static boolean equals(BigDecimal bigNum1, BigDecimal bigNum2) { - Assert.notNull(bigNum1); - Assert.notNull(bigNum2); + //noinspection NumberEquality + if (bigNum1 == bigNum2){ + return true; + } + if (bigNum1==null || bigNum2==null){ + return false; + } return 0 == bigNum1.compareTo(bigNum2); }