Browse Source

ArrayUtil add equals

Looly 5 years ago
parent
commit
67f6225e1f

+ 1 - 0
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过来的玩笑导致的问题

+ 6 - 307
hutool-core/src/main/java/cn/hutool/core/builder/EqualsBuilder.java

@@ -39,6 +39,8 @@ import java.util.Set;
  *   return EqualsBuilder.reflectionEquals(this, obj);
  * }
  * </pre>
+ *
+ * 来自Apache Commons Lang改造
  */
 public class EqualsBuilder implements Builder<Boolean> {
 	private static final long serialVersionUID = 1L;
@@ -47,8 +49,6 @@ public class EqualsBuilder implements Builder<Boolean> {
 	 * <p>
 	 * A registry of objects used by reflection methods to detect cyclical object references and avoid infinite loops.
 	 * </p>
-	 *
-	 * @since 3.0
 	 */
 	private static final ThreadLocal<Set<Pair<IDKey, IDKey>>> REGISTRY = new ThreadLocal<>();
 
@@ -379,35 +379,13 @@ public class EqualsBuilder implements Builder<Boolean> {
 			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;
 	}
 
@@ -544,285 +522,6 @@ public class EqualsBuilder implements Builder<Boolean> {
 	}
 
 	/**
-	 * <p>Performs a deep comparison of two <code>Object</code> arrays.</p>
-	 *
-	 * <p>This also will be called for the top level of
-	 * multi-dimensional, ragged, and multi-typed arrays.</p>
-	 *
-	 * @param lhs the left hand <code>Object[]</code>
-	 * @param rhs the right hand <code>Object[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>long</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(long, long)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>long[]</code>
-	 * @param rhs the right hand <code>long[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>int</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(int, int)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>int[]</code>
-	 * @param rhs the right hand <code>int[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>short</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(short, short)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>short[]</code>
-	 * @param rhs the right hand <code>short[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>char</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(char, char)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>char[]</code>
-	 * @param rhs the right hand <code>char[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>byte</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(byte, byte)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>byte[]</code>
-	 * @param rhs the right hand <code>byte[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>double</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(double, double)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>double[]</code>
-	 * @param rhs the right hand <code>double[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>float</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(float, float)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>float[]</code>
-	 * @param rhs the right hand <code>float[]</code>
-	 * @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;
-	}
-
-	/**
-	 * <p>Deep comparison of array of <code>boolean</code>. Length and all
-	 * values are compared.</p>
-	 *
-	 * <p>The method {@link #append(boolean, boolean)} is used.</p>
-	 *
-	 * @param lhs the left hand <code>boolean[]</code>
-	 * @param rhs the right hand <code>boolean[]</code>
-	 * @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;
-	}
-
-	/**
 	 * <p>Returns <code>true</code> if the fields that have been checked
 	 * are all equal.</p>
 	 *

+ 9 - 11
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;
 	}
 
 	/**

+ 46 - 0
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);
+		}
+	}
 }

+ 7 - 2
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);
 	}