Мне было просто интересно узнать - почему Arrays.equals(double [] [], double [] []) возвращает 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 и печатает "Equal". Работает ли этот метод только с отдельными измерениями? если да, то что-то подобное для многомерных массивов в Java?
Ответ 1
Используйте deepEquals(Object[], Object[])
.
Возвращает true
, если два указанных массива глубоко равны друг другу.
Так как a int[]
является instanceof Object
, a 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
предоставляет утилиту static
equals(int[], int[])
.
System.out.println(
java.util.Arrays.equals(
new int[] {1,2},
new int[] {1,2}
)
); // prints "true"
Массив массивов в Java
- An
int[]
является instanceof Object
- An
int[][]
- это instanceof Object[]
-
int[][]
НЕ a 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
, если два указанных массива Objects
равны друг другу. Два массива считаются equal
, если оба массива содержат одинаковое количество элементов, а все соответствующие пары элементов в двух массивах равны. Два объекта 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
.