— Риша, мне прямо не терпится узнать об остальных методах класса Arrays.
— Такое рвение к учёбе не может не радовать старого учителя!..Впрочем, если ты так уж хотел всё разузнать, добрый волшебник Google тебе в помощь и днём, и ночью.
— Ээээ…
— Шучу. Отчасти. Конечно я расскажу лучше, но если что — помни о добром волшебнике. И сегодняшнюю лекцию я начну с метода, который называется Arrays.fill
— Очень часто у Java-программистов при работе с массивами возникает задача: заполнить массив одинаковыми значениями. Можно, конечно, написать цикл и просто в цикле присвоить каждой ячейке массива определенное значение:
int[] x = new int[100];
for (int i = 0; i < x.length; i++)
x[i] = 999;
— Вместо всего этого можно вызвать метод Arrays.fill()
, который делает ровно то же самое: заполняет переданный массив переданным значением. Вот как это выглядит:
Arrays.fill(имя, значение)
И код из примера выше можно сделать немного компактнее и понятнее:
int[] x = new int[100];
Arrays.fill(x, 999);
— Красиво!
— А еще с помощью метода Arrays.fill()
можно заполнить определенным значением не весь массив, а его часть:
Arrays.fill(имя, первый, последний, значение)
— Где первый и последний — это номера первой и последней ячеек, которые нужно заполнить.
— По старой доброй (или не очень доброй) традиции Java, последний элемент не входит в диапазон.
Пример:
|
Заполняем ячейки x[3] , x[4] , x[5] , x[6] значениями 999 . Нумерация ячеек массива с нуля!Переменная str содержит значение"[1, 2, 3, 999, 999, 999, 999, 8, 9, 10]" |
— Метод Arrays.fill()
работает только с одномерными массивами. Если в него передать двумерный массив, он будет обработан как одномерный, со всеми вытекающими последствиями.
Arrays.copyOf()
— Амиго, ответь, пожалуйста, как поменять размер контейнера массива после его создания?
— Эммм… Вопрос с подвохом, насколько я понял? Но я уже не настолько зелёный. Правильный ответ: никак! Нельзя поменять размер контейнера массива после его создания.
— А если очень хочется?
— Всё равно нельзя!
— На самом деле, если очень хочется, то можно! С помощью программистского финта:
- Сначал создаёшь новый массив нужной длины
- Затем копируешь в него все элементы из первого массива.
— Именно эти два действия делает метод Arrays.copyOf()
. Вот как выглядит его вызов:
тип[] имя2 = Arrays.copyOf(имя, длина);
— Этот метод не меняет существующий массив, вместо этого он создает новый массив и копирует в него элементы старого массива.
— А что если длина нового массива меньше длины существующего?
— Отличный вопрос, Амиго! Если элементы не поместились, то лишние значения просто игнорируются.
— А если наоборот, остались лишние ячейки, что в них изначально находится?
— Если длина нового массива больше длины старого, ячейки заполняются нулями.
Пример:
|
Переменная str2 содержит значение"[1, 2, 3, 4, 5]" Переменная str3 содержит значение"[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 0, 0, 0, 0, 0]" |
Arrays.copyOfRange()
— А что делать, если тебе нужно получить массив длиной 5 из массива длины 10, но чтобы в нем оказались не первые 5 элементов, а 5 последних? Для этого случая тебе понадобится еще один метод класса Arrays
. Называется он Arrays.copyOfRange()
. Вот как выглядит его вызов:
тип[] имя2 = Arrays.copyOfRange(имя, первый, последний);
— Этот метод тоже создает новый массив, но заполняет его данными из произвольного места исходного массива. Где первый и последний — это номера первой и последней ячеек, которые должны быть в новом массиве. Можешь сказать, входит ли в этот диапазон последний элемент?
— Ха! Как говаривал мой великий учитель, «по старой доброй традиции Java, последний элемент не входит в диапазон».
— Амиго, ты растёшь буквально на глазах.
Пример:
|
Переменная str2 содержит значение"[16, 17, 18, 19, 20]" Переменная str3 содержит значение"[16, 17, 18, 19, 20, 0, 0, 0, 0, 0]" |
Arrays.sort()
— Ну и напоследок я оставил самое...ммм… приятное — сортировку. В программировании сортировать массивы приходится очень часто. Вот тебе топ-3 самых популярных действий при работе с массивами:
- Сортировка массива
- Поиск минимального (или максимального) элемента массива
- Определение индекса элемента в массиве (поиск элемента в массиве)
— Эффективные алгоритмы сортировки, надо сказать, не так уж просто написать. Точнее, это нормальная задачка, и тебе, как ученику, иногда не помешает поупражняться в написании алгоритмов сортировок. Но в работе лучше не тратить время на изобретение велосипеда. Разработчики Java включили в класс Arrays
метод sort()
. Вот как выглядит его вызов:
Arrays.sort(имя);
Этот метод сортирует переданный массив по возрастанию.
Пример:
|
Переменная str содержит значение"[-20, -20, -20, -2, 0, 3, 8, 11, 99, 999]" |
— Отлично! Вызвал один метод, и отсортированный массив готов. Красота!
— Кстати, сортировать можно не только весь массив, но и часть массива. Вот как выглядит его вызов:
Arrays.sort(имя, первый, последний);
— Где первый и последний — это номера первой и последней ячеек, которых должна коснуться сортировка. И…
— Я уже знаю, что ты скажешь! «По старой доброй традиции Java, последний элемент не входит в диапазон».
Пример:
|
Переменная str содержит значение"[11, -2, 3, 0, -20, -20, 8, 999, 99, -20]" |
— В Java для сортировки массивов используется самый быстрый алгоритм сортировки — QuickSort. Скорость его сортировки зависит от размера массива и рассчитывается по формуле N*Log(N).
— Сортировка массива из 1000 элементов будет содержать около 10,000 сравнений ячеек массива. Сортировка массива из миллиона элементов будет содержать около 20 миллионов сравнений.
— Не так уж и много сравнений, если учесть количество элементов!
— Вот и я об этом же. Алгоритм QuickSort — очень эффективный.
Arrays.binarySearch()
— Ну и последний из самых интересных методов класса Arrays
умеет искать заданное значение в массиве. Это не обычный поиск, а так называемый бинарный поиск. Суть его заключается вот в чем:
- Предварительно массив сортируется.
- Затем средний элемент массива сравнивается с искомым (с тем, который мы ищем).
- Если искомый больше среднего, поиск продолжается в правой половине массива.
- Если искомый элемент меньше среднего, поиск продолжается в левой половине массива.
— Благодаря тому, что массив отсортирован, можно за одно сравнение отбросить половину массива. Затем на следующем шаге отбросить еще половину и так далее.
— Класс! Идём к цели прям очень быстро!
— Точно. В массиве из миллиона(!) элементов алгоритм бинарного поиска может найти индекс нужного элемента всего за 20 сравнений. Минусом алгоритма является то, что массив предварительно нужно отсортировать, а сортировка тоже занимает время.
Вот как выглядит его вызов:
int index = Arrays.binarySearch(имя, значение);
— Где имя
— это имя массива, который нужно передать уже отсортированным (например, с помощью функции Arrays.sort()
). значение
— это тот элемент, который ищется в массиве. Метод возвращает результат — индекс искомого элемента в массиве (номер ячейки массива).
Примеры:
|
x содержит{-20, -20, -20, -2, 0, 3, 8, 11, 99, 999} 4 1 (также подходили индексы 0 и 2 )8 -7 |
— А что, если искомых элементов в массиве несколько?
— Правильный вопрос, Амиго. В таком случае алгоритм вернет номер одного из них (нет гарантий, что это будет, допустим, самый первый или наоборот — самый последний из одинаковых элементов).
— А если в массиве вообще нет того, что мы ищем?
— В таком случае алгоритм вернёт отрицательный индекс.
Документация
— Всё понятно, Риша! Было очень интересно.
— Если тебе прям вот очень интересно, то полистай на досуге официальную документацию по классу Arrays
и его методах в на сайте Oracle:
https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Arrays.html
— Можешь присмотреться, например, к методам Arrays.mismatch()
и Arrays.compare()
. Скорее всего, ты найдешь им полезное применение.
— И пусть тебя не смущает количество методов — там у каждого метода есть 5-10 копий, которые отличаются только типом параметров.
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ