Java:如何测试数组是否相等?

46
以下代码为什么会输出 "Different."
答:
boolean[][] a = { {false,true}, {true,false} };
boolean[][] b = { {false,true}, {true,false} };

if (Arrays.equals(a, b) || a == b)
    System.out.println("Equal.");
else
    System.out.println("Different.");

7
我总是先测试 a == b 或者不测试。如果 equals 为真,第二个表达式应该总是为真。 - Peter Lawrey
10
标准实现已经包括了这个检查,所以我个人会将其排除。 - aioobe
它应该只指出两者都是假的。 - user905686
1
@PeterLawrey 实际上,你的意思是如果 == 为真,则 equals 应该为真。 - ealfonso
4个回答

78
由于Arrays.equals执行的是浅层比较,所以代码会打印"Different."。由于数组从Object继承了它们的equals方法,因此将为内部数组执行标识比较,这将失败,因为ab不引用相同的数组。如果更改为Arrays.deepEquals,则会按预期打印"Equal."

文档中说到Array.equals:“如果两个指定的对象数组相等,则返回true。如果两个数组包含相同数量的元素,并且两个数组中对应的元素对相等,则认为这两个数组是相等的。”那么这不意味着完全比较吗...? - user905686
1
不行,因为ab的元素不能互相 equals(...)。自己试试:a [0] .equals(b [0]),你会发现它是假的。 - aioobe
在调用 deepEquals 之前检查 a == b 会更好,不是吗? - Victor Sorokin
2
不,最好完全省略那个冗余。 (Arrays.equals 的标准实现已经从那个检查开始了。) - aioobe
1
请注意,Arrays.equals 对于单维数组是足够的:在这个例子中,Arrays.equals(a[0], b[0]) 是真的。 - Stephen Schaub

17

这并不是显而易见的。

首先,== 运算符只比较两个指针。因为 ab 是位于不同内存地址的不同对象,所以 a == b 将返回 false。(嘿,Java 纯洁主义者,我知道 == 实际上比较的是 对象标识。我只是在尝试讲解)。

现在让我们看一下数组的 equals() 实现:

boolean[] c = new boolean[] { false, true, false };
boolean[] d = new boolean[] { false, true, false };

if (c.equals(d)) {
    System.out.println("Equals");
} else {
    System.out.println("Not equals");
}

这将打印Not equals,因为没有任何数组实例实现了equals()方法。所以,当我们调用<somearray>.equals(<otherarray>)时,实际上是调用了Object.equals()方法,它只是比较两个指针。

即使如此,要注意你的代码实际上正在做以下事情:

boolean[] a0 = new boolean[] { false, true };
boolean[] a1 = new boolean[] { true, false };
boolean[] b0 = new boolean[] { false, true };
boolean[] b1 = new boolean[] { true, false };
boolean[][] a = new boolean[][] { a0, a1 };
boolean[][] b = new boolean[][] { b0, b1 };

if (Arrays.equals(a, b) || a == b)
    System.out.println("Equal.");
else
    System.out.println("Different.");

Arrays.equals(a, b) 最终会调用 a0.equals(b0),并且它会返回 false。因此,Arrays.equals(a, b) 也会返回 false

所以你的代码将打印出 Different.,我们可以得出结论:Java 中的相等性有时可能比较棘手。


6

对于多维数组,请使用Arrays.deepEquals()。


哈哈,谢谢,这正是我已经寻找了很长时间的答案。 - Все Едно

-1
public static boolean equal(double[][] a, double[][] b) {
        if (a == null) {
            return (b == null);
        }
        if (b == null) {
            return false;  // already know 'a' isn't null
        }
        if (a.length != b.length) {
            return false;
        }
        for (int i = 0; i < a.length; i++) {
            if (!Arrays.equals(a[i], b[i])) {
                return false;
            }
        }
        return true;
    }

6
重新实现Arrays.deepEquals并不是一个好的做法。到目前为止给出了良好的解释和解决方案。 - user905686

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接