W3docs

Основные операции с массивами Java

Основные операции с массивами в Java — длина, копирование, заполнение, поиск и преобразование в список.

Сами по себе массивы имеют очень мало методов. Объект массива предоставляет одно поле (length) и один метод (clone()). Всё остальное — вывод, заполнение, поиск, сравнение — находится в служебном классе java.util.Arrays, который подробно рассматривается в следующей главе. Эта глава — обзор повседневных операций: что они делают и какой вызов использовать.

На этой странице рассматриваются: чтение размера, вывод, заполнение, сравнение, поиск, копирование и преобразование массива в List. Для каждой задачи, как правило, существует один идиоматический вызов — цель состоит в том, чтобы понять, какой именно.

Длина

int[] data = {3, 1, 4, 1, 5, 9, 2, 6};
System.out.println(data.length);   // 8

Это поле, а не метод — без скобок. Значение length фиксируется при создании массива; чтобы «увеличить» массив, нужно выделить новый и скопировать данные (см. Копирование ниже). Обратите внимание: length — это поле массивов, тогда как у String и коллекций, таких как List, используется метод length() или size() — распространённый источник путаницы.

Вывод массива

System.out.println(arr) печатает что-то вроде [I@1540e19d — имя класса и хэш. Почти всегда это не то, что нужно. Используйте Arrays.toString:

import java.util.Arrays;

int[] data = {3, 1, 4, 1, 5};
System.out.println(Arrays.toString(data));   // [3, 1, 4, 1, 5]

Для двумерных массивов используйте Arrays.deepToString:

int[][] grid = {{1, 2}, {3, 4}};
System.out.println(Arrays.deepToString(grid));   // [[1, 2], [3, 4]]

Заполнение

Чтобы присвоить всем элементам одинаковое значение:

int[] zeros = new int[5];
Arrays.fill(zeros, 7);              // {7, 7, 7, 7, 7}

Форма с диапазоном заполняет только [fromIndex, toIndex):

int[] data = new int[10];
Arrays.fill(data, 3, 7, 1);         // ones in positions 3, 4, 5, 6

Равенство

== для массивов сравнивает ссылки, а не содержимое. Для поэлементного сравнения используйте Arrays.equals:

int[] a = {1, 2, 3};
int[] b = {1, 2, 3};
System.out.println(a == b);                    // false (different objects)
System.out.println(Arrays.equals(a, b));       // true

Для вложенных массивов используйте Arrays.deepEquals. В части семантики, допускающей null, оба метода считают null == null равным true.

Поиск

Линейный перебор с классическим циклом подходит для небольших массивов или массивов с неизвестным порядком:

int[] data = {7, 3, 9, 1, 5};
int target = 9;
int found = -1;
for (int i = 0; i < data.length; i++) {
  if (data[i] == target) { found = i; break; }
}

Для отсортированного массива Arrays.binarySearch работает за O(log n):

int[] sorted = {1, 3, 5, 7, 9};
int idx = Arrays.binarySearch(sorted, 7);   // 3

Если значение не найдено, binarySearch возвращает отрицательное число, кодирующее позицию, где оно должно было бы находиться: -(insertionPoint) - 1. Например, возврат -8 означает «не найдено, должно быть на индексе 7». Чтобы получить точку вставки: int insert = -(result) - 1;.

Информация
Arrays.binarySearch работает только с отсортированным массивом. При неотсортированных данных исключение не выбрасывается — метод молча вернёт неверный или непредсказуемый результат. Сначала отсортируйте массив (Arrays.sort) или используйте линейный поиск, если массив не упорядочен.

Копирование

Чтобы получить новый массив с тем же содержимым:

int[] data = {1, 2, 3, 4, 5};
int[] copy = Arrays.copyOf(data, data.length);

Для изменения размера при копировании — добавление значений по умолчанию если новый массив длиннее, усечение если короче:

int[] longer  = Arrays.copyOf(data, 8);    // {1, 2, 3, 4, 5, 0, 0, 0}
int[] shorter = Arrays.copyOf(data, 3);    // {1, 2, 3}

Для копирования среза:

int[] middle = Arrays.copyOfRange(data, 1, 4);   // {2, 3, 4}

from включительно, to исключительно — стандартное полуоткрытое соглашение Java.

Единственный метод копирования, находящийся непосредственно на объекте массива, — это clone():

int[] data = {1, 2, 3};
int[] dup  = data.clone();          // {1, 2, 3}, a separate array

clone() выполняет поверхностное копирование: для массива объектов (или двумерного массива, который является массивом массивов) внутренние ссылки разделяются, а не дублируются. Подробнее о копировании — включая System.arraycopy и глубокое копирование — рассказывается в отдельной главе Copying arrays.

Преобразование в List

Arrays.asList(...) оборачивает массив (из ссылочных типов) как List фиксированного размера:

String[] arr = {"a", "b", "c"};
List<String> list = Arrays.asList(arr);

Список фиксированного размера: add/remove выбрасывают UnsupportedOperationException, но list.set(...) допустим. Обратите внимание, что asList не работает с примитивными массивами так, как можно было бы ожидать — Arrays.asList(new int[]{1, 2, 3}) возвращает List<int[]> длиной 1, а не List<Integer>. Для примитивов используйте потоки:

import java.util.stream.IntStream;

int[] nums = {1, 2, 3};
List<Integer> boxed = IntStream.of(nums).boxed().toList();

Хэширование

Arrays.hashCode(arr) вычисляет хэш на основе содержимого, который можно использовать в реализациях equals/hashCode содержащего класса:

int[] data = {1, 2, 3};
int h = Arrays.hashCode(data);

Для вложенных массивов используйте Arrays.deepHashCode.

Практический пример

java— editable, runs on the server

Что дальше

Вспомогательные методы, которые вы только что использовали — toString, fill, equals, copyOf, binarySearch, sort — все находятся в одном классе: java.util.Arrays. Следующая глава систематически рассматривает служебный класс Arrays, включая аспекты, которые здесь были рассмотрены вскользь.

Практика

Практика
Что выведет System.out.println(arr) для int[]?
Что выведет System.out.println(arr) для int[]?
Was this page helpful?