Как вывести массив в Java
Вывод массивов в Java: Arrays.toString, Arrays.deepToString и форматирование через потоки.
Передача массива напрямую в System.out.println почти никогда не печатает то, что ожидается — вместо элементов вы увидите что-то вроде [I@1b6d3586. Массивы не переопределяют toString(), поэтому версия из Object печатает тип и хэш идентичности. В этой главе показаны идиоматические решения: Arrays.toString для одномерных массивов, Arrays.deepToString для вложенных, String.join для произвольных разделителей и ручной цикл, когда нужен полный контроль.
Почему обычный вывод не работает
Метод toString(), который массив наследует от Object, возвращает сигнатуру класса и хэш-код — но не содержимое:
int[] numbers = {3, 1, 4};
System.out.println(numbers); // [I@1b6d3586
System.out.println("" + numbers); // same reference string[I означает «массив int»; шестнадцатеричное число после @ — это хэш идентичности, который меняется от запуска к запуску. Конкатенация массива со строкой не помогает, поскольку конкатенация тоже вызывает toString(). Решение — использовать вспомогательный метод для форматирования элементов.
Arrays.toString для одного измерения
java.util.Arrays.toString обходит одномерный массив и возвращает читаемую строку с элементами через запятую в квадратных скобках:
int[] numbers = {3, 1, 4, 1, 5};
System.out.println(Arrays.toString(numbers)); // [3, 1, 4, 1, 5]
String[] words = {"alpha", "beta"};
System.out.println(Arrays.toString(words)); // [alpha, beta]Метод перегружен для каждого примитивного типа массива (int[], double[], boolean[], …) и для Object[], поэтому работает с любым плоским массивом. Для массивов объектов вызывается собственный toString() каждого элемента.
Arrays.deepToString для вложенных массивов
Arrays.toString заходит только на один уровень вглубь. Для двумерного массива он форматирует внешний массив, но каждый внутренний печатает как ссылку. Используйте Arrays.deepToString, чтобы рекурсивно обойти все уровни:
int[][] grid = {{1, 2}, {3, 4}};
System.out.println(Arrays.toString(grid)); // [[I@..., [I@...]
System.out.println(Arrays.deepToString(grid)); // [[1, 2], [3, 4]]Применяйте deepToString всякий раз, когда массив содержит другие массивы — матрицы, зубчатые массивы, массивы массивов объектов.
| Подход | Лучше всего для | Формат вывода |
|---|---|---|
Arrays.toString | Одномерные примитивные или объектные массивы | [a, b, c] |
Arrays.deepToString | Вложенные / многомерные массивы | [[a, b], [c, d]] |
String.join | String[] с произвольным разделителем | a, b, c (без скобок) |
ручной цикл / StringBuilder | Полный контроль над форматом | любой нужный формат |
Пользовательское форматирование
Когда формат по умолчанию со скобками не подходит, String.join объединяет String[] (или любой итерируемый CharSequence) с выбранным разделителем без окружающих скобок:
String[] words = {"alpha", "beta", "gamma"};
System.out.println(String.join(" | ", words)); // alpha | beta | gammaДля нестроковых массивов или полностью произвольного вывода цикл с StringBuilder даёт полный контроль над разделителями, префиксами и форматированием каждого элемента. Ещё один вариант — потоки: Arrays.stream(arr).mapToObj(String::valueOf).collect(Collectors.joining(", ")).
Запускаемый пример
Программа ниже сравнивает подходы: Arrays.toString для плоского int[] и String[], разницу между мелким и глубоким обходом для двумерного массива, String.join для произвольного разделителя и ручной StringBuilder. Строка shallow проверяет, содержит ли мелкий toString двумерного массива внутренние ссылки, поэтому печатает стабильное true вместо изменяющегося от запуска к запуску хэша.
Что следует вынести из результата запуска:
toString: [3, 1, 4, 1, 5]показывает, какArrays.toStringпревращает плоскийint[]в читаемый текст в квадратных скобках.words: [alpha, beta, gamma]подтверждает, что тот же метод работает с массивами объектов, вызываяtoString()каждого элемента.shallow: trueдоказывает, чтоArrays.toStringприменительно к двумерному массиву оставляет внутренние массивы как ссылки[[I@..., именно поэтому результат начинается с[[I@.deep: [[1, 2], [3, 4]]показывает, какArrays.deepToStringрекурсивно заходит во вложенные массивы и печатает каждый элемент.joined: alpha | beta | gammaиmanual: {3; 1; 4; 1; 5}демонстрируют, какString.joinи цикл сStringBuilderформируют вывод без скобок с произвольным разделителем.