equals && deepEquals

equals && deepEquals

本文分为以下几个部分

equals

deepEquals

总结

equals

首先说明:这里说的 equalsjava.util.Arrays#equals 的,不是 java.lang.Object#equals 下的。

当我们比较两个数组中的每个值是否相等时(俩数组大小是一样的情况下),经常会用循环去判断

public static void main(String[] args) {
    String[] a = {"a","b"};
    String[] b = {"a","b"};
    int len = a.length;
    boolean flag = true;
    for(int i = 0; i < len; i++){
        if(!a[i].equals(b[i])){
            flag = false;
            break;
        }
    }
    //输出:a 和 b 数组相同
    System.out.println("a 和 b 数组" + (flag ? "相同" : "不相同"));
}

实际上java提供了一种直接比较的方法 equals

public static void main(String[] args) {
    String[] a = {"a","b"};
    String[] b = {"a","b"};
    //输出:a 和 b 数组相同
    System.out.println("a 和 b 数组" + (Arrays.equals(a,b) ? "相同" : "不相同"));
}

equals的源码如下

/**
 * Returns <tt>true</tt> if the two specified arrays of Objects are
 * <i>equal</i> to one another.  The two arrays are considered equal if
 * both arrays contain the same number of elements, and all corresponding
 * pairs of elements in the two arrays are equal.  Two objects <tt>e1</tt>
 * and <tt>e2</tt> are considered <i>equal</i> if <tt>(e1==null ? e2==null
 * : e1.equals(e2))</tt>.  In other words, the two arrays are equal if
 * they contain the same elements in the same order.  Also, two array
 * references are considered equal if both are <tt>null</tt>.<p>
 *
 * @param a one array to be tested for equality
 * @param a2 the other array to be tested for equality
 * @return <tt>true</tt> if the two arrays are equal
 */
public static boolean equals(Object[] a, Object[] a2) {
    //判断是否为同一个东西,即是否地址相同
    if (a==a2)
        return true;
    
    //再判断 a 或者 a2 中是否有为空的情况
    if (a==null || a2==null)
        return false;
    
    //判断长度
    int length = a.length;
    if (a2.length != length)
        return false;

    
    for (int i=0; i<length; i++) {
        Object o1 = a[i];
        Object o2 = a2[i];
        //注意 Object 的 equals 是 ==
        //比较两个值,由于不是 new 出来的,若o1、o2值相同的话,o1、o2指向的是常量池的同一个东西
        if (!(o1==null ? o2==null : o1.equals(o2)))
            return false;
    }

    return true;
}

所以以后直接调用 Arrays.equals 就可以啦,甚至都不用管里面大小啊,是否为空啊,都帮你判断好了。

我们再来试一下多维数组

public static void main(String[] args) {
    String[][] a = {{"a"},{"b"}};
    String[][] b = {{"a"},{"b"}};
    //输出:a 和 b 数组不相同
    System.out.println("a 和 b 数组" + (Arrays.equals(a,b) ? "相同" : "不相同"));
}

这次对于二维数组输出的是不相同,思考一下,进去的比较的是 {"a"}.equals{"a"} , 此时比较的是两个数组,Object的比较肯定会出现问题,那么我们修改一下,循环判断每个数组。

public static void main(String[] args) {
    String[][] a = {{"a"},{"b"}};
    String[][] b = {{"a"},{"b"}};
    int len = a.length;
    boolean flag = true;
    for(int i = 0; i < len; i++){
        if(!Arrays.equals(a[i],b[i])){
            flag = false;
        }
    }
    //输出:a 和 b 数组相同
    System.out.println("a 和 b 数组" + (flag ? "相同" : "不相同"));
}

二维的可以循环一次,那三维的岂不是要循环两次?多维的岂不是更离谱?

Java早就想到了这个问题,所以提供了一种方法deepEquals。

deepEquals

deepEquals 深层等于,判断多维数组每个值是否相同,话不多说,看代码

public static void main(String[] args) {
    String[][] a = {{"a"},{"b"}};
    String[][] b = {{"a"},{"b"}};
    //输出:a 和 b 数组相同
    System.out.println("a 和 b 数组" + (Arrays.deepEquals(a,b) ? "相同" : "不相同"));
}

输出的是 a 和 b 相同,我们看一下源码:

/**
 * Returns <tt>true</tt> if the two specified arrays are <i>deeply
 * equal</i> to one another.  Unlike the {@link #equals(Object[],Object[])}
 * method, this method is appropriate for use with nested arrays of
 * arbitrary depth.
 *
 * <p>Two array references are considered deeply equal if both
 * are <tt>null</tt>, or if they refer to arrays that contain the same
 * number of elements and all corresponding pairs of elements in the two
 * arrays are deeply equal.
 *
 * <p>Two possibly <tt>null</tt> elements <tt>e1</tt> and <tt>e2</tt> are
 * deeply equal if any of the following conditions hold:
 * <ul>
 *    <li> <tt>e1</tt> and <tt>e2</tt> are both arrays of object reference
 *         types, and <tt>Arrays.deepEquals(e1, e2) would return true</tt>
 *    <li> <tt>e1</tt> and <tt>e2</tt> are arrays of the same primitive
 *         type, and the appropriate overloading of
 *         <tt>Arrays.equals(e1, e2)</tt> would return true.
 *    <li> <tt>e1 == e2</tt>
 *    <li> <tt>e1.equals(e2)</tt> would return true.
 * </ul>
 * Note that this definition permits <tt>null</tt> elements at any depth.
 *
 * <p>If either of the specified arrays contain themselves as elements
 * either directly or indirectly through one or more levels of arrays,
 * the behavior of this method is undefined.
 *
 * @param a1 one array to be tested for equality
 * @param a2 the other array to be tested for equality
 * @return <tt>true</tt> if the two arrays are equal
 * @see #equals(Object[],Object[])
 * @see Objects#deepEquals(Object, Object)
 * @since 1.5
 */
public static boolean deepEquals(Object[] a1, Object[] a2) {
    //前面判断和equals一样
    if (a1 == a2)
        return true;
    if (a1 == null || a2==null)
        return false;
    int length = a1.length;
    if (a2.length != length)
        return false;

    //循环取出,注意未使用length方法
    for (int i = 0; i < length; i++) {
        Object e1 = a1[i];
        Object e2 = a2[i];

        if (e1 == e2)
            continue;
        if (e1 == null)
            return false;

        // Figure out whether the two elements are equal
        //调用 deepEquals0 方法判断是否相同
        boolean eq = deepEquals0(e1, e2);

        if (!eq)
            return false;
    }
    return true;
}

static boolean deepEquals0(Object e1, Object e2) {
    assert e1 != null;
    boolean eq;
    //多维数组递归调用,再未变成最后一层数组时,会一直调用进入第一个 if 结果中
    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;
}

从源码中看到,deepEquals同样可以在一维数组中使用

public static void main(String[] args) {
    String[] a = {"a","b"};
    String[] b = {"a","b"};
    //输出:a 和 b 数组相同
    System.out.println("a 和 b 数组" + (Arrays.deepEquals(a,b) ? "相同" : "不相同"));
}

总结

在一维数组中,使用 Arrays.equals 或者 Arrays.deepEquals 都可以帮你判断其中的值是否相同。

但在二维及以上,使用 Arrays.deepEquals 会比 Arrays.equals 方便(需要写递归或者循环判断,过于复杂)。

posted @ 2021-06-11 17:07  抱糖果彡  阅读(163)  评论(0编辑  收藏  举报