ArrayUtil add equals

This commit is contained in:
Looly 2020-09-08 16:47:15 +08:00
parent fd51eb08b4
commit 67f6225e1f
5 changed files with 69 additions and 320 deletions

View File

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

View File

@ -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;
}
@ -543,285 +521,6 @@ public class EqualsBuilder implements Builder<Boolean> {
return this;
}
/**
* <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>

View File

@ -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 loolyApache-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;
}
/**

View File

@ -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);
}
}
}

View File

@ -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);
}