JavaRush /Курсы /Java Syntax New Beta /Класс Arrays, часть 2

Класс Arrays, часть 2

Java Syntax New Beta
6 уровень , 8 лекция
Открыта

Риша, мне прямо не терпится узнать об остальных методах класса 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, последний элемент не входит в диапазон.

Пример:

int[] x = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

Arrays.fill(x, 3, 7, 999);


String str = Arrays.toString(x);

Заполняем ячейки x[3], x[4], x[5], x[6] значениями 999. Нумерация ячеек массива с нуля!

Переменная str содержит значение
"[1, 2, 3, 999, 999, 999, 999, 8, 9, 10]"

— Метод Arrays.fill() работает только с одномерными массивами. Если в него передать двумерный массив, он будет обработан как одномерный, со всеми вытекающими последствиями.

6
Задача
Java Syntax Pro, 6 уровень, 8 лекция
Недоступна
Заполняем массив
Реализуй статический метод main(String[]), который заполняет массив array значениями valueStart и valueEnd. Если длина массива четная, его первую половину нужно заполнить значениями valueStart, а вторую — valueEnd. Если длина массива нечётная, то первую большую часть заполнить значениями valueStart

Arrays.copyOf()

— Амиго, ответь, пожалуйста, как поменять размер контейнера массива после его создания?

Эммм… Вопрос с подвохом, насколько я понял? Но я уже не настолько зелёный. Правильный ответ: никак! Нельзя поменять размер контейнера массива после его создания.

— А если очень хочется?

Всё равно нельзя!

— На самом деле, если очень хочется, то можно! С помощью программистского финта:

  1. Сначал создаёшь новый массив нужной длины
  2. Затем копируешь в него все элементы из первого массива.

— Именно эти два действия делает метод Arrays.copyOf(). Вот как выглядит его вызов:

тип[] имя2 = Arrays.copyOf(имя, длина);

— Этот метод не меняет существующий массив, вместо этого он создает новый массив и копирует в него элементы старого массива.

А что если длина нового массива меньше длины существующего?

— Отличный вопрос, Амиго! Если элементы не поместились, то лишние значения просто игнорируются.

А если наоборот, остались лишние ячейки, что в них изначально находится?

— Если длина нового массива больше длины старого, ячейки заполняются нулями.

Пример:

int[] x = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};

int[] x2 = Arrays.copyOf(x, 5);
String str2 = Arrays.toString(x2);

int[] x3 = Arrays.copyOf(x, 15);
String str3 = Arrays.toString(x3);


Переменная 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, последний элемент не входит в диапазон».

— Амиго, ты растёшь буквально на глазах.

Пример:

int[] x = {11, 12, 13, 14, 15, 16, 17, 18, 19, 20};

int[] x2 = Arrays.copyOfRange(x, 5, 10);
String str2 = Arrays.toString(x2);

int[] x3 = Arrays.copyOfRange(x, 5, 15);
String str3 = Arrays.toString(x3);


Переменная str2 содержит значение
"[16, 17, 18, 19, 20]"

Переменная str3 содержит значение
"[16, 17, 18, 19, 20, 0, 0, 0, 0, 0]"
6
Задача
Java Syntax Pro, 6 уровень, 8 лекция
Недоступна
Делим массив
Реализуй метод main(String[]), который делит массив array на два подмассива и заполняет ими двумерный массив result. Если длина массива нечетная, то большую часть нужно скопировать в первый подмассив. Для разделения массива используй метод Arrays.copyOfRange(int[], int, int). Порядок элементов не м

Arrays.sort()

— Ну и напоследок я оставил самое...ммм… приятное — сортировку. В программировании сортировать массивы приходится очень часто. Вот тебе топ-3 самых популярных действий при работе с массивами:

  • Сортировка массива
  • Поиск минимального (или максимального) элемента массива
  • Определение индекса элемента в массиве (поиск элемента в массиве)

— Эффективные алгоритмы сортировки, надо сказать, не так уж просто написать. Точнее, это нормальная задачка, и тебе, как ученику, иногда не помешает поупражняться в написании алгоритмов сортировок. Но в работе лучше не тратить время на изобретение велосипеда. Разработчики Java включили в класс Arrays метод sort(). Вот как выглядит его вызов:

Arrays.sort(имя);

Этот метод сортирует переданный массив по возрастанию.

Пример:

int[] x = {11, -2, 3, 0, 999, -20, 8, -20, 99, -20};

Arrays.sort(x);
String str = Arrays.toString(x);


Переменная str содержит значение
"[-20, -20, -20, -2, 0, 3, 8, 11, 99, 999]"

Отлично! Вызвал один метод, и отсортированный массив готов. Красота!

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

Arrays.sort(имя, первый, последний);

— Где первый и последний — это номера первой и последней ячеек, которых должна коснуться сортировка. И…

Я уже знаю, что ты скажешь! «По старой доброй традиции Java, последний элемент не входит в диапазон».

Пример:

int[] x = {11, -2, 3, 0, 999, -20, 8, -20, 99, -20};

Arrays.sort(x, 4, 8);
String str = Arrays.toString(x);


Переменная str содержит значение
"[11, -2, 3, 0, -20, -20, 8, 999, 99, -20]"

— В Java для сортировки массивов используется самый быстрый алгоритм сортировки — QuickSort. Скорость его сортировки зависит от размера массива и рассчитывается по формуле N*Log(N).

— Сортировка массива из 1000 элементов будет содержать около 10,000 сравнений ячеек массива. Сортировка массива из миллиона элементов будет содержать около 20 миллионов сравнений.

Не так уж и много сравнений, если учесть количество элементов!

— Вот и я об этом же. Алгоритм QuickSort — очень эффективный.

6
Задача
Java Syntax Pro, 6 уровень, 8 лекция
Недоступна
Сортировка массива
Реализуй метод main(String[]), который сортирует массив array по возрастанию. Для сортировки массива используй метод Arrays.sort(int[]).

Arrays.binarySearch()

— Ну и последний из самых интересных методов класса Arrays умеет искать заданное значение в массиве. Это не обычный поиск, а так называемый бинарный поиск. Суть его заключается вот в чем:

  • Предварительно массив сортируется.
  • Затем средний элемент массива сравнивается с искомым (с тем, который мы ищем).
  • Если искомый больше среднего, поиск продолжается в правой половине массива.
  • Если искомый элемент меньше среднего, поиск продолжается в левой половине массива.

— Благодаря тому, что массив отсортирован, можно за одно сравнение отбросить половину массива. Затем на следующем шаге отбросить еще половину и так далее.

— Класс! Идём к цели прям очень быстро!

— Точно. В массиве из миллиона(!) элементов алгоритм бинарного поиска может найти индекс нужного элемента всего за 20 сравнений. Минусом алгоритма является то, что массив предварительно нужно отсортировать, а сортировка тоже занимает время.

Вот как выглядит его вызов:

int index = Arrays.binarySearch(имя, значение);

— Где имя — это имя массива, который нужно передать уже отсортированным (например, с помощью функции Arrays.sort()). значение — это тот элемент, который ищется в массиве. Метод возвращает результат — индекс искомого элемента в массиве (номер ячейки массива).

Примеры:

int[] x = {11, -2, 3, 0, 999, -20, 8, -20, 99, -20};
Arrays.sort(x);

int index1 = Arrays.binarySearch(x, 0);
int index2 = Arrays.binarySearch(x, -20);
int index3 = Arrays.binarySearch(x, 99);
int index4 = Arrays.binarySearch(x, 5);
x содержит
{-20, -20, -20, -2, 0, 3, 8, 11, 99, 999}

4
1 (также подходили индексы 0 и 2)
8
-7

А что, если искомых элементов в массиве несколько?

— Правильный вопрос, Амиго. В таком случае алгоритм вернет номер одного из них (нет гарантий, что это будет, допустим, самый первый или наоборот — самый последний из одинаковых элементов).

А если в массиве вообще нет того, что мы ищем?

— В таком случае алгоритм вернёт отрицательный индекс.

6
Задача
Java Syntax Pro, 6 уровень, 8 лекция
Недоступна
Есть ли кто?
Реализуй метод main(String[]), который выводит в консоль true, если элемент содержится в переданном массиве, иначе — false. Массив array не должен изменять расположение своих элементов. Для поиска элемента в массиве нужен бинарный поиск. Чтобы это сделать, используй статический метод Arrays.binaryS

Документация

Всё понятно, Риша! Было очень интересно.

— Если тебе прям вот очень интересно, то полистай на досуге официальную документацию по классу Arrays и его методах в на сайте Oracle:

https://docs.oracle.com/en/java/javase/14/docs/api/java.base/java/util/Arrays.html

— Можешь присмотреться, например, к методам Arrays.mismatch() и Arrays.compare(). Скорее всего, ты найдешь им полезное применение.

— И пусть тебя не смущает количество методов — там у каждого метода есть 5-10 копий, которые отличаются только типом параметров.

Комментарии (39)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
YouSSR Уровень 14
2 августа 2023
Я бы внес правку в текст этого урока. Arrays.binarySearch() Необходимо предварительно отстортировать массив
Lafaed Уровень 36
26 октября 2022
Если есть кнопочка "правильное решение" тогда не вижу смысла запрещать постить ответы. *моё решение* // (совершенно точно правильное) public static void main(String[] args) { boolean result = Arrays.binarySearch(array,element) > -1 ? true : false; System.out.println(result); } У меня вопрос : По какой логике, имея в консоли правильный ответ (пробовал и boolean и String), условие : "При вызове метода main(String[]) вывести в консоли true, если значение переменной element содержится в массиве." - не выполняется ?
Anonymous #3283984 Уровень 24
15 апреля 2023
плюсую, тоже пока не могу пробить эту скалу! по факту все работает, а валидация вывода в консоль true не проходит
aiiirborne Уровень 29
29 сентября 2022
Откуда вы взяли Ришу? Здесь везде Диего!
Х-50 Уровень 24
12 сентября 2022
ЭЭЭ. я ЧТОТО НЕ ПОНЯЛ. Моё решение последней задачи выдаёт правильный результат- но не проходит. public class Solution { public static int[] array = {9, 8, 7, 6, 5, 4, 3, 2, 1}; //System.out.println(array()); public static int element = 5; public static void main(String[] args) { int search = Arrays.binarySearch(array, element); boolean result = true; if(search == -1){ result = false ; } System.out.println(result);//напишите тут ваш код } } Сравнил с тем что даётся как эталон правильного ответа- ну мне не понятна логика задания. То, что написал я -намного проще и понятнее. И исходный массив не меняет. Зачем тогда так заморачиваться как это сделали в задании и образце решения??? зачем в задаче использовать сортировку массива?! Если метод Arrays.binarySearch прекрасно работает без неё, а в тексте задания сказано исходный масив не менять...Ну не понимаю чтото я крепко. Помогите пожалуйста
Qunjavi Уровень 10
23 июля 2022
Немного про mismatch Метод Arrays.mismatch(array1, array2) сравнивает два массива и в результате мы получаем индекс, где есть расхождение. Если нет расхождений, получим -1. Если есть расхождения, получим номер индекса.

int[] array1 = {1 , 9 , 3 , 4, 5};
int[] array2 = {1 , 2 , 3 , 4, 5};
System.out.println(Arrays.mismatch(array1, array2)); //получим индекс 1
Немного про compare Этот метод лексикографически сравнивает первый отличающийся элемент массива. Нужно не для того, чтобы найти какой массив больше, а где есть бОльший элемент. Если элемент первого массива лексикографически больше, то получим 1; в противном случаем получим -1. Если массивы лексикографически равны, получим 0. При разном размере массивов можно получить число больше одного, это будет указывать что первый массив лексикографически больше на столько-то.

//элементы одинаковы
int[] array1 = {2, 3, 4};
int[] array2 = {2, 3, 4};
System.out.println(Arrays.compare(array1, array2)); //получим 0

//первый массив длинней, но это не важно в compare
int[] array1 = {2, 3, 4, 0};
int[] array2 = {3, 3, 4};
System.out.println(Arrays.compare(array1, array2)); //получим -1 -- второй массив хоть по длине меньше, но так как 3 больше 2 лексикографически, получим именно -1
Qunjavi Уровень 10
23 июля 2022
Условие задачи "Делим массив" как-то коряво сформулировано, может кому понравится моя формулировка, в ней содержится маленькая подсказка. Реализуй метод main(String[]), который скопирует ряд элементов из первой половины массива array в result[0] , а вторую половину в result[1]. При чем если длина массива array нечетная, то бОльшая его часть должна копироваться в result[0]. Для копирования элементов и "разделения" массива используй метод Arrays.copyOfRange(int[], int, int). Порядок элементов не меняй.
22 июля 2022
Почему аватар имеет изображение Диего, а речь идет от лица Риши?
Никита Уровень 11
26 мая 2022
В задаче "заполняем массив" в методе Arrays.fill нужно указывать array.length/2 (Я заменил это выражение переменной, и задача не засчитывалась).
KirStranger Уровень 21
18 апреля 2022
Вторую лекцию подряд разговаривает с Ришей а на аве Диего.
Роман Уровень 33
14 апреля 2022
для обоих строк используйте copyOfRange, хотя для одной можно использовать и просто copy , и результат будет верный, но валидатор не пропускает