Java Arrays.equals () возвращает false для двумерных матриц

Мне было просто любопытно знать - почему делает Arrays.equals (дважды [] [], дважды [] []) возвращают false? когда на самом деле массивы имеют то же число элементов, и каждый элемент является тем же?

Например, я выполнил следующий тест.

double[][] a,  b;
int size =5;

a=new double[size][size];
b=new double[size][size];

for( int i = 0; i < size; i++ )
    for( int j = 0; j < size; j++ ) {
        a[i][j]=1.0;
        b[i][j]=1.0;
    }

if(Arrays.equals(a, b))
    System.out.println("Equal");
else
    System.out.println("Not-equal");

Возвращает false и печатает "Не - равный".

с другой стороны, если у меня есть что-то вроде этого:

double[] a,  b;
int size =5;

a=new double[size];
b=new double[size];

for( int i = 0; i < size; i++ ){
    a[i]=1.0;
    b[i]=1.0;
} 

if(Arrays.equals(a, b))
    System.out.println("Equal");
else
    System.out.println("Not-equal");

возвращает true и печатает "Равный". Метод только работает с единственными размерами? если так, есть ли что-то подобное для многомерных массивов в Java?

39
задан Bill the Lizard 27 April 2010 в 12:22
поделиться

1 ответ

Используйте deepEquals(Object[], Object[]).

Возвращает true, если два указанных массива глубоко равны друг другу.

Поскольку int[] является instanceof Object, int[][] является instanceof Object[].


Что касается почему Arrays.equals не "работает" для двумерных массивов, то это можно объяснить пошагово следующим образом:

Для массивов equals определяется в терминах идентичности объектов

System.out.println(
    (new int[] {1,2}).equals(new int[] {1,2})
); // prints "false"

Это происходит потому, что массивы наследуют свои equals от своего общего суперкласса, Object.

Конечно, часто нам действительно нужно равенство значений для массивов, поэтому java.util.Arrays предоставляет статический метод equals(int[], int[]).

System.out.println(
    java.util.Arrays.equals(
        new int[] {1,2},
        new int[] {1,2}
    )
); // prints "true"

Массив массивов в Java

  • An int[] is an instanceof Object
  • An int[][][] is an instanceof Object[]
  • An int[][][] is NOT an instanceof int[]

Java на самом деле не имеет двумерных массивов. У нее даже нет многомерных массивов. В Java есть массивы массивов.

java.util.Arrays.equals является "неглубоким"

Теперь рассмотрим этот фрагмент:

System.out.println(
    java.util.Arrays.equals(
        new int[][] {
            { 1 },
            { 2, 3 },
        },
        new int[][] {
            { 1 },
            { 2, 3 },
        }
    )
); // prints "false"

Вот факты:

  • Каждый аргумент является Object[]
    • Элемент с индексом 0 является int[] { 1 }
    • Элемент с индексом 1 является int[] { 2, 3 }.
  • Есть два Object[] экземпляра
  • Есть четыре int[] экземпляра

Из предыдущего пункта должно быть ясно, что это вызывает Arrays.equals(Object[], Object[]) перегрузку. Из API:

Возвращает true, если два указанных массива объектов равны друг другу. Два массива считаются равными, если оба массива содержат одинаковое количество элементов, и все соответствующие пары элементов в двух массивах равны. Два объекта e1 и e2 считаются равными, если (e1==null ? e2==null : e1.equals(e2)).

Теперь должно быть понятно, почему приведенный фрагмент выводит "false"; это потому, что элементы массивов Object[] не равны по приведенному выше определению (поскольку int[] имеет свои equals, определяемые идентичностью объекта).

java.util.Arrays.deepEquals является "глубоким"

В отличие от этого, вот что делает Arrays.deepEquals(Object[], Object[]) :

Возвращает true, если два указанных массива глубоко равны друг другу. В отличие от метода equals(Object[],Object[]), этот метод подходит для использования с вложенными массивами произвольной глубины.

System.out.println(
    java.util.Arrays.deepEquals(
        new int[][] {
            { 1 },
            { 2, 3 },
        },
        new int[][] {
            { 1 },
            { 2, 3 },
        }
    )
); // prints "true"

О Arrays.toString и Arrays.deepToString

Стоит отметить аналогию между этими двумя методами и тем, что мы обсуждали до сих пор в отношении вложенных массивов.

System.out.println(
    java.util.Arrays.toString(
        new int[][] {
            { 1 },
            { 2, 3 },
        }
    )
); // prints "[[I@187aeca, [I@e48e1b]"

System.out.println(
    java.util.Arrays.deepToString(
        new int[][] {
            { 1 },
            { 2, 3 },
        }
    )
); // prints "[[1], [2, 3]]"

Опять же, рассуждения аналогичны: Arrays.toString(Object[]) рассматривает каждый элемент как Object, и просто вызывает его метод toString(). Массивы наследуют свой toString() от своего общего суперкласса Object.

Если вы хотите, чтобы java.util.Arrays учитывал вложенные массивы, вам нужно использовать deepToString, так же как и deepEquals.

111
ответ дан 27 November 2019 в 02:10
поделиться
Другие вопросы по тегам:

Похожие вопросы: