1. Класс Arrays

Как мы уже раньше говорили, массивы — очень полезная и часто используемая вещь в программировании.

Создатели Java очень скоро заметили, что Java-программисты часто пишут один и тот же код при работе с массивами. Например: «скопировать часть массива в другой массив», «заполнить все ячейки массива одинаковыми значениями», «вывести содержимое массива в удобно читаемом виде на экран» и т.п.

Поэтому они сделали специальный класс – Arrays (полное имя java.util.Arrays), в который поместили самые популярные действия при работе с массивами.

В нем очень много методов на все случаи жизни, но для начала мы рассмотрим только 10 из них — самые простые и часто используемые.


2. Метод Arrays.toString()

И первый метод, который мы рассмотрим, будет называться Arrays.toString(). Но для начала немного предыстории.

У каждого массива в Java есть метод toString(), который возвращает «текстовое представление массива». Получить текстовое представление массива можно с помощью такой конструкции:

String str = имя.toString();

Где имя — это имя переменной-массива, а str — это имя переменной, в которую сохранится строковое представление массива.

Но если вы попробуете вывести массив на экран с помощью метода System.out.println(имя), скорее всего увидите что-то типа:

I@37afeb11

Первая буква I означает, что это массив типа int, а символы после @ – адрес массива в памяти. С одной стороны, переменная-массив именно эту информацию и хранит, а с другой — мы ожидали иное, правда?

Хотелось бы увидеть значения, которые есть в массиве! И вот для того, чтобы увидеть именно значения массива, и придумали метод Arrays.toString(). Его вызов выглядит так:

String str = Arrays.toString(имя);

Примеры:

int[] array = {1, 2, 3};
String str = Arrays.toString(array);
Переменная str будет содержать строковое значение:
"[1, 2, 3]"
int[] array = {};
String str = Arrays.toString(array);
Переменная str будет содержать строковое значение:
"[]"
String[] array = {"Привет", "Как", "Дела"};
String str = Arrays.toString(array);
Переменная str будет содержать строковое значение:
"[Привет, Как, Дела]"


3. Метод Arrays.deepToString()

Но если вы с помощью метода Arrays.toString() попробуете преобразовать в строку (вывести на экран) двумерный массив, увидите кое-что знакомое:

[I@37afeb11, I@37afeb21, I@37afeb31]

А все дело в том, что в ячейках двумерного массива хранятся ссылки на одномерные массивы. А одномерные массивы как преобразовываются в строку? Именно так, как вы видите выше.

И что же делать? Как нам получить правильное отображение двумерного массива?

Для этого у класса Arrays есть еще один специальный метод — deepToString(). Вызов его выглядит так:

String str = Arrays.deepToString(имя);

В этот метод можно передать двумерный, одномерный, трехмерный и вообще массив любой размерности, и он всегда будет отображать элементы массива.
Обрати внимание: метод Arrays.deepToString() не работает с одномерными массивами примитивов (например, int[]).

Примеры:

Integer[] array = {1, 2, 3};
String str = Arrays.deepToString(array);
Переменная str будет содержать строковое значение:
"[1, 2, 3]"
int[][] array = { {1, 1}, {2, 2}, {3, 3} };
String str = Arrays.deepToString(array);
Переменная str будет содержать строковое значение:
"[[1, 1], [2, 2], [3, 3]]"
int[][][] array = { {{1, 2, 3}, {1}}, {{}} };
String str = Arrays.deepToString(array);
Переменная str будет содержать строковое значение:
"[[[1, 2, 3], [1]], [[]]]"


4. Метод Arrays.equals()

С выводом массивов на экран мы разобрались, а что насчет сравнения массивов?

Для сравнения строк у нас были методы equals и equalsIgnoreCase, а какие методы есть у массивов?

Хорошая новость: у массивов есть метод equals, и плохая новость — он не сравнивает содержимое массивов. Метод equals у массивов делает то же самое, что и оператор == – сравнивает ссылки.

Примеры:

int[] x1 = {1, 2, 3};
int[] x2 = {1, 2, 3};
boolean b = x1 == x2;


false (ссылки не равны)
int[] x1 = {1, 2, 3};
int[] x2 = {1, 2, 3};
x1.equals(x2);
Метод equals у массивов банально сравнивает ссылки двух массивов.

false (ссылки не равны)

И что же делать? Как сравнить массивы по их содержанию?

И опять нам на выручку приходит класс Arrays, а вернее, его метод Arrays.equals() Выглядит его вызов так:

Arrays.equals(имя1, имя2)

Метод возвращает true (истина), если массивы равной длины и их элементы равны. Иначе возвращает false (ложь).

Примеры:

int[] x1 = {1, 2, 3};
int[] x2 = {1, 2, 3};
x1.equals(x2);
Метод equals у массивов банально сравнивает ссылки двух массивов.

false (ссылки не равны)
int[] x1 = {1, 2, 3};
int[] x2 = {1, 2, 3};
Arrays.equals(x1, x2);


true (содержимое массивов равно)
int[] x1 = {1, 2, 3};
int[] x2 = {1, 2, 3, 4};
Arrays.equals(x1, x2);


false (содержимое массивов отличается)

5. Метод Arrays.deepEquals()

И как вы уже, наверное, догадываетесь, метод Arrays.equals для двумерных массивов будет работать неправильно: он работает с двумерным массивом как с одномерным, элементы которого — адреса одномерных массивов.

Поэтому, чтобы правильно сравнивать многомерные массивы (n=1, 2, 3, ...), придумали метод Arrays.deepEquals(). Выглядит его вызов так:

Arrays.deepEquals(имя1, имя2)

Метод возвращает true (истина), если массивы равной длины и их элементы равны. Иначе возвращает false (ложь). Если элементы внутри массива — тоже массивы, для их сравнения используется метод Arrays.deepEquals() и т.д.

Примеры:

int[][] x1 = {{1, 2, 3}, {4, 5, 6}};
int[][] x2 = {{1, 2, 3}, {4, 5, 6}};
x1.equals(x2);
Метод equals у массивов банально сравнивает ссылки двух массивов.

false (ссылки не равны)
int[][] x1 = {{1, 2, 3}, {4, 5, 6}};
int[][] x2 = {{1, 2, 3}, {4, 5, 6}};
Arrays.equals(x1, x2);
Метод Arrays.equals сравнит x1 и x2 как одномерные массивы, которые хранят ссылки. Ссылки в них хранятся разные.
false (содержимое массивов неравно)
int[][] x1 = {{1, 2, 3}, {4, 5, 6}};
int[][] x2 = {{1, 2, 3}, {4, 5, 6}};
Arrays.deepEquals(x1, x2);


true (содержимое массивов равно)