User Professor Hans Noodles
Professor Hans Noodles
41 уровень

Класс Arrays и его использование

Статья из группы Java Developer
И снова привет! :) Класс Arrays и его использование - 1На прошлом занятии мы познакомились с такой структурой данных как массив (Java array), научились создавать массивы, наполнять данными, а также узнали, как они хранятся в памяти. Сегодня мы рассмотрим некоторые задачи и примеры работы с массивами, которые часто будут встречаться тебе в реальной работе. Например, представь себе такую ситуацию: у нас есть массив из 10 чисел, записанных в случайном порядке.

//array Java, example
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
Наша задача состоит в том, чтобы отсортировать этот массив по возрастанию: от меньших чисел к большим. В итоге он должен выглядеть так:

[-234, -2, 16, 26, 35, 43, 80, 92, 99, 167]
Как нам это сделать? Задача нетривиальная, такого мы еще не делали :/ Есть какие-то идеи? Попробуй предположить. Вот что, например, мы можем сделать:
  • Пройтись по всем элементам массива. Сравнивать каждый элемент со следующим ([0] с [1], [1] с [2], [2] с [3] и т.д.). Если текущий элемент массива больше следующего, меняем их местами и переходим к следующему элементу. Если нет — оставляем как есть и идем дальше.

  • Таким образом, после первого прохождения по элементам массива самое большое значение (167) гарантированно будет в последней ячейке.

  • Теперь снова пройдем по всем элементам массива начиная с элемента с индексом [0], но до предпоследнего элемента (самое большое число уже на своем месте) и сделаем такие же сравнения и замены местами. 
    В конце в предпоследней ячейке у нас окажется второе самое большое значение (99).

  • Повторим эту работу столько раз, сколько у нас в массиве элементов минус один.
Класс Arrays и его использование - 2Идею мы придумали, осталось только написать код. Выглядеть он будет так:

public class Main {

   public static void main(String[] args) {
      
       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       for (int i = numbers.length - 1; i > 0; i--) {
           for (int j = 0; j < i; j++) {
           /*Сравниваем элементы попарно,
             если они имеют неправильный порядок,
             то меняем местами*/
               if (numbers[j] > numbers[j + 1]) {
                   int tmp = numbers[j];
                   numbers[j] = numbers[j + 1];
                   numbers[j + 1] = tmp;
               }
           }
       }

   }
}
Эээ… Выглядит несколько сложновато -_- Даже если общий принцип работы понятен, приходится писать довольно много кода, чтобы решить такую несложную с виду задачу. Окей, может мы просто переоценили себя? Наверное, задача, которую мы взяли, пока слишком сложна для нас. Давай попробуем сделать что попроще. Например, возьмем тот же массив чисел.

int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
Наша задача — скопировать его содержимое в другой массив.

int [] numbersCopy = new int[10];
Подумай, как бы ты это сделал, используя те знания о массивах, которые у тебя уже есть? Можно, например, пройтись в цикле по массиву numbers и по очереди записывать его элементы в numbersCopy:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       int [] numbersCopy = new int[10];
      
       for (int i = 0; i < numbers.length; i++) {
          
           numbersCopy[i] = numbers[i];
       }

   }
}
Ну-у-у, тут мы более-менее справились! Задача вроде как решена, хоть опять же: если ее нужно будет выполнять часто, в коде будет куча одинаковых циклов. На самом деле, эти и другие задачи уже давно решены создателями Java, и нам не нужно “изобретать велосипед” и писать какой-то код собственного решения. Класс Arrays и его использование - 3

Класс Java Arrays

Решать типовые задачи при работе с массивами тебе поможет специальный класс Java — Arrays. В этот класс были добавлены методы для решения самых распространенных задач, с которыми сталкиваются Java-программисты в работе. Например, задачу по сортировке массива, для которой мы сами пытались придумать решения, решается в одну строку:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};
      
       Arrays.sort(numbers);

       System.out.println(Arrays.toString(numbers));

   }
}
Метод Arrays.sort() выполняет сортировку массива. Причем заложенный в него алгоритм делает это намного эффективнее того кода, который написали мы. Вывод на консоль:

[-234, -2, 16, 26, 35, 43, 80, 92, 99, 167]
Обрати внимание: для преобразования массива в строку мы использовали еще один метод класса ArraysArrays.toString(). Сами по себе массивы в Java не переопределяют метод toString(). Поэтому если ты напишешь просто

System.out.println(numbers.toString());
будет вызван метод toString() класса Object. В случае с массивами вывод будет примерно такой:

[I@4554617c
Не будем сейчас подробно разбираться, почему вывод именно такой, главное — это явно не то, что нам нужно. А вот Arrays.toString() сделал то, что мы и хотели. Кстати, наша задача с копированием тоже легко решается в классе Arrays:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       int [] numbersCopy = Arrays.copyOf(numbers, numbers.length);
       System.out.println(Arrays.toString(numbersCopy));

   }
}
В метод Arrays.copyOf() мы передаем наш оригинальный массив (из которого надо скопировать значения) и длину нового массива, в который мы копируем данные. В данном случае в качестве длины мы указали numbers.length, т.к. хотим скопировать массив целиком. Если же мы хотим скопировать только несколько первых элементов, можно указать длину для нового массива меньше:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       int [] numbersCopy = Arrays.copyOf(numbers, 4);
       System.out.println(Arrays.toString(numbersCopy));

   }
}
Здесь мы указали длину нового массива, равного 4. Соответственно, только 4 первых элемента numbers будут скопированы в новый массив. Вывод в консоль:

[167, -2, 16, 99]
Кстати, если нужно скопировать часть массива, но не с начала, а “из середины”, Arrays позволяет сделать и это:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       int [] numbersCopy = Arrays.copyOfRange(numbers, 2,6);
       System.out.println(Arrays.toString(numbersCopy));

   }
}
Вывод:

[16, 99, 26, 92]
В новый массив были скопированы числа из ячеек со второй (включительно) по шестую (не включительно). Кроме того, нам может понадобиться сравнить два массива между собой. Так же, как с методом toString(), сами по себе массивы не переопределяют метод equals(). Поэтому если мы попробуем сравнить их так:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {1, 2, 3};
       int[] numbers2 = {1, 2, 3};

       System.out.println(numbers.equals(numbers2));
   }
}
получим результат false. Ведь будет вызван метод Object.equals(), который сравнивает ссылки. А они, естественно, разные! Но нам-то надо сравнить содержимое массивов, а не ссылки. Класс Arrays содержит переопределенный метод equals(), который делает ровно то, что нам нужно:

public class Main {

   public static void main(String[] args) {

       int[] numbers = {1, 2, 3};
       int[] numbers2 = {1, 2, 3};

       System.out.println(Arrays.equals(numbers, numbers2));
   }
}
Вывод:

true
Кстати, класс Arrays успешно работает не только с обычными массивами, но и с двумерными:

public class Main {

   public static void main(String[] args) {

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

       int[][] numbersCopy = Arrays.copyOf(numbers, numbers.length);

       System.out.println("Равны ли эти двумерные массивы между собой?");
       System.out.println(Arrays.deepEquals(numbers, numbersCopy));
      
       System.out.println(Arrays.deepToString(numbersCopy));
   }
}
Вывод:

Равны ли эти двумерные массивы между собой?
true
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
Как видишь, метод Arrays.copyOf() справился с копированием и двумерного массива. Обрати внимание, что в таком случае при копировании двумерного массива происходит так называемое "поверхностное копирование". А для сравнения двумерных массивов и их вывода на консоль предусмотрены специальные методы — deepEquals и deepToString(); В будущем ты еще не раз увидишь (и порадуешься этому), что создатели Java предусмотрели очень много типовых ситуаций, с которыми сталкиваются программисты при работе, и реализовали в языке готовые решения для них. Использовать эти решения гораздо проще и удобнее, чем изобретать велосипеды, верно? :) Обязательно почитай документацию класса Arrays на сайте Oracle. Удачи в обучении!
Комментарии (105)
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION
Артем Уровень 16 Москва
23 июля 2021
Ребят, подскажите, пожалуйста, почему для перевода массива в строку мы пишем Arrays.toString(array) вместо array.toString()? В статье про статические методы был пример, что нестатические методы в неявном виде так и работают - вызывается метод КЛАССА и в него первым аргументом передается ссылка на объект, в каком месте здесь ошибка?
Anonymous #2599412 Уровень 0
18 мая 2021
int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80}; for (int i = numbers.length - 1; i > 0; i--) { for (int j = 0; j < i; j++) { /*Сравниваем элементы попарно, если они имеют неправильный порядок, то меняем местами*/ if (numbers[j] > numbers[j + 1]) { int tmp = numbers[j]; numbers[j] = numbers[j + 1]; numbers[j + 1] = tmp; Обьясните кто нибудь этот код, вообще непойму.java учу 6 месяцев но этот цикл и условие непйому.можно по пальцам
Kuksh Уровень 14
27 апреля 2021

int[] numbers = {167, -2, 16, 99, 26, 92, 43, -234, 35, 80};

       Arrays.sort(numbers);

       System.out.println(Arrays.toString(numbers));
Выводит в виде [-234, -2, ..., 99] А можно ли выводить без скобок каким-то еще методом? Или только через консоль и цикл for/for-each можно чистым текстом вывести в консоль: -234, -2, ..., 99 без []. И имеет ли какое-то это вообще принципиальне значение именно в программировании для каких-то конкретных задач или затем как-то избавляются от этих скобок? Просто пока решаем задачи - здесь я так понимаю валидатор такое не пропустит же ибо тебя просят отсортировать список и вывести в консосль, а тут раз и появляются скобки. С технической точки зрения получается задание выполнено, а с точки зрения Пользователя - ему допустим не хочется видеть какие-то не понятные скобки.
N1k0 Уровень 22 Санкт-Петербург Россия
12 апреля 2021
Сделал тест скорости работы сортировок на массиве: {4, 76, 3, 66, 99, -99, 1, 0, -5, -2} Результат: Пузырьковая сортировка 4500 наносекунд Сортировка выбором 2400 наносекунд Сортировка вставками 1800 наносекунд Челночная сортировка 2700 наносекунд Дефолтная Array.sort сортировка 189900 наносекунд Вывод: На маленьких массивах простые сортировки быстрее работают чем Array.sort Дополнительно: Подал на вход массивы с разным кол-вом элементов, Array.sort начинает отрабатывать настолько же быстро, как и простейшие алгоритмы, при массивах более 200 элементов (примерно), а при массивах в 10 000 элементов Array.sort отрабатывает более чем в 10 раз быстрее.
Alex Boy Уровень 20 Кривой Рог Гондурас
22 марта 2021
Ну вот почему такие статьи выдаются уже после выполнения задач с участием массивов? Будь у меня эти знания пару лекция назад, я бы не разбивал руки в кровь решая задачи на копирование или сортировку массивов, не зная этих методов))) На самом деле я понимаю зачем авторы курса так сделали и это интересно решать задачи с минимальным набором знаний, но все же иногда это такая боль...))))
Рустам Уровень 10 Казань
2 декабря 2020
Талантливо объясняет.
Максим Щербенко Уровень 8 Одесса Украина
21 октября 2020
Ну вот такая хорошая статья, все доходчиво расписано, один вопрос у меня, специально не упомянули такую важную малость что класс Arrays надо импортироват? И что он находится в import java.util.Arrays? Что за одержимость давать возможность погуглить все вокруг? Это же растягивает, и без того, длительное обучение
Yuliya Уровень 18
28 сентября 2020
Спасибо за статью! Очень помогла.)))
aleksdenni Уровень 22 Полтава Украина
27 сентября 2020
Про ArrayList статью такого качества , было б не плохо . А в целом - много полезной инфы.
🦔 Виктор Уровень 20 Москва Россия Expert
25 сентября 2020
Спасибо, отличная статья с отличными примерами. Обязательна к прочтению! Забрал к себе на канал.