Objects.equals と Objects.deepEquals の違い

Objects.equals ソースコード (java.util.Objects#equals)

public static boolean equals(Object a, Object b) {
    
    
    return (a == b) || (a != null && a.equals(b));
}

Objects.equals と equals の間に違いはなく、null の処理を​​増やすのに役立つだけであり、次
のように理解できます:
Objects.equals = equals + null の処理

Objects.equals(null, null);       true
Objects.equals(null, "null");     false
Objects.equals("null", null);     false
Objects.equals("null", "null");   true

Objects.deepEquals ソースコード (java.util.Objects#deepEquals)

public static boolean deepEquals(Object a, Object b) 
    if (a == b)
        return true;
    else if (a == null || b == null)
        return false;
    else
        return Arrays.deepEquals0(a, b);
}


static boolean deepEquals0(Object e1, Object e2) {
    
    
    assert e1 != null;
    boolean eq;
    if (e1 instanceof Object[] && e2 instanceof Object[])
        eq = deepEquals ((Object[]) e1, (Object[]) e2);
    else if (e1 instanceof byte[] && e2 instanceof byte[])
        eq = equals((byte[]) e1, (byte[]) e2);
    else if (e1 instanceof short[] && e2 instanceof short[])
        eq = equals((short[]) e1, (short[]) e2);
    else if (e1 instanceof int[] && e2 instanceof int[])
        eq = equals((int[]) e1, (int[]) e2);
    else if (e1 instanceof long[] && e2 instanceof long[])
        eq = equals((long[]) e1, (long[]) e2);
    else if (e1 instanceof char[] && e2 instanceof char[])
        eq = equals((char[]) e1, (char[]) e2);
    else if (e1 instanceof float[] && e2 instanceof float[])
        eq = equals((float[]) e1, (float[]) e2);
    else if (e1 instanceof double[] && e2 instanceof double[])
        eq = equals((double[]) e1, (double[]) e2);
    else if (e1 instanceof boolean[] && e2 instanceof boolean[])
        eq = equals((boolean[]) e1, (boolean[]) e2);
    else
        eq = e1.equals(e2);
    return eq;
}

これは次のように理解できます:
Objects.deepEquals = equals + null の処理 + 配列の処理 = Objects.equals + 配列の処理


使用するシーン

配列ではない通常のオブジェクト

String a = "abc";
String b = "abc";

System.out.println(a.equals(b));               true
System.out.println(Objects.equals(a, b));      true
System.out.println(Objects.deepEquals(a, b));  true

String覆写了的equals()
Person per1 = new Person("name");
Person per2 = new Person("name");

System.out.println(per1.equals(per2));                true
System.out.println(Objects.equals(per1, per2));       true
System.out.println(Objects.deepEquals(per1, per2));   true

因为Person@Data,故覆写了equals

プリミティブ型の配列

int[] arr1 = {
    
    1, 2, 3};
int[] arr2 = arr1;
int[] arr3 = {
    
    1, 2, 3};

System.out.println(arr1.equals(arr2));  true
System.out.println(arr1.equals(arr3));  false
数组没有覆写equals,故会使用Object.equals,比较的是地址

System.out.println(Objects.equals(arr1, arr2));  true
System.out.println(Objects.equals(arr1, arr3));  false
数组没有覆写equals,故会使用Object.equals,比较的是地址

System.out.println(Objects.deepEquals(arr1, arr2));  true
System.out.println(Objects.deepEquals(arr1, arr3));  true
deepEquals自己有判断逻辑,调用ArraysSupport.mismatch去比较,本地是调用了元素自身的equals方法

オブジェクトタイプの配列

String[] arr1 = {
    
    "Tom", "Mary"};
String[] arr2 =arr1;
String[] arr3 = {
    
    "Tom", "Mary"};

System.out.println(arr1.equals(arr2));  true
System.out.println(arr1.equals(arr3));  false

System.out.println(Objects.equals(arr1, arr2));  true
System.out.println(Objects.equals(arr1, arr3));  false

System.out.println(Objects.deepEquals(arr1, arr2));  false
System.out.println(Objects.deepEquals(arr1, arr3));  true

和基本类型的数组一样结论
@Data
public class Person {
    
    
    private String personName;
    public Person(String name) {
    
    
        personName = name;
    }
}

Person per1 = new Person("name1");
Person per2 = new Person("name2");
Person[] arr1 = new Person[] {
    
    per1, per2};
Person[] arr2 = new Person[] {
    
    per1, per2};
System.out.println(arr1.equals(arr2));               false 数组没有覆写equals,故会使用Object.equals,比较的是地址
System.out.println(Objects.deepEquals(arr1, arr2));  true  Person复写了equals,故为值比较

Person[] arr3 = new Person[] {
    
    new Person("name1"), new Person("name2")};
Person[] arr4 = new Person[] {
    
    new Person("name1"), new Person("name2")};
System.out.println(arr3.equals(arr4));               false 数组没有覆写equals,故会使用Object.equals,比较的是地址
System.out.println(Objects.deepEquals(arr3, arr4));  true  Person复写了equals,故为值比较
public class Person {
    
    
    private String personName;
    public Person(String name) {
    
    
        personName = name;
    }
}

Person per1 = new Person("name1");
Person per2 = new Person("name2");
Person[] arr1 = new Person[] {
    
    per1, per2};
Person[] arr2 = new Person[] {
    
    per1, per2};
System.out.println(arr1.equals(arr2));               false 数组没有覆写equals,故会使用Object.equals,比较的是地址
System.out.println(Objects.deepEquals(arr1, arr2));  true  按顺序比较元素的地址

Person[] arr1 = new Person[] {
    
    per1, per2};
Person[] arr2 = new Person[] {
    
    per2, per1};
System.out.println(arr1.equals(arr2));               false 数组没有覆写equals,故会使用Object.equals,比较的是地址
System.out.println(Objects.deepEquals(arr1, arr2));  false 按顺序比较元素的地址

Person[] arr3 = new Person[] {
    
    new Person("name1"), new Person("name2")};
Person[] arr4 = new Person[] {
    
    new Person("name1"), new Person("name2")};
System.out.println(arr3.equals(arr4));               false 数组没有覆写equals,故会使用Object.equals,比较的是地址
System.out.println(Objects.deepEquals(arr3, arr4));  false 按顺序比较元素的地址

結論は

2 つの配列の内容が同じかどうかを比較する場合は、deepEquals を使用します。
配列内のオブジェクト メンバーが equals メソッドをオーバーライドしていない場合、このメソッドの使用はお勧めできません。また、比較する方法さえありません。 、アドレスのみを比較できるため

参考文献

hashCode()とequals()の関係は、
equals、Objects.equals、Objects.deepEqualsの違いと接続です。

おすすめ

転載: blog.csdn.net/weixin_37646636/article/details/132185595