Вывести определенный элемент массива java
Метод Arrays.copyOf() принимает 2 параметра: копируемый массив и количество копируемых значений, которое определяет также длину нового массива. Т. к. мы хотим скопировать массив целиком, то указываем в качестве количества длину исходного массива.
Если вам требуется скопировать не весь массив, а только какую-то его часть, то вместо длины следует указать необходимое значение: это может быть как целочисленный литерал, так и значение переменной.
Следует иметь ввиду небольшой нюанс работы метода, связанный с тем, что если количество копируемых элементов указано больше, чем их содержит массив, то copyOf() дополнит итоговый массив значениями по умолчанию.
Пусть имеется заполненный массив чисел, в который необходимо добавить еще одно число. Т. к. размер уже созданного массива менять нельзя, то создадим новый с увеличенным размером:
int[] srcArr = ; int[] destArr = Arrays.copyOf(srcArr, srcArr.length + 3); System.out.println(Arrays.toString(destArr)); destArr[srcArr.length] = 6; destArr[srcArr.length + 1] = 7; System.out.println(Arrays.toString(destArr));
[1, 2, 3, 4, 5, 0, 0, 0] [1, 2, 3, 4, 5, 6, 7, 0]
String[] letters = ; int len = letters.length; int newLen = len + (int) (len * 0.75); System.out.println("Длина нового массива = " + newLen); String[] destArr = Arrays.copyOf(letters, newLen); System.out.println(Arrays.toString(destArr)); destArr[len] = "D"; System.out.println(Arrays.toString(destArr));
Длина нового массива = 5 [A, B, C, null, null] [A, B, C, D, null]
В данном коде создаются два массива типа String. Длина второго массива (newLen) вычисляется по формуле, которая позволяет увеличивать его размер на 75%. Также видно, что copyOf заполняет пустые ячейки null’ом.
Если требуется скопировать значения не с начала массива (или не до конца), то необходимо использовать Arrays.copyOfRange() (появился в Java 1.6). Данный метод позволяет копировать определенный диапазон значений массива, начиная с указанного индекса:
int[] srcArr = ; int[] destArr = Arrays.copyOfRange(srcArr, 1, 3); System.out.println(Arrays.toString(destArr));
Метод copyOfRange() принимает 3 параметра: исходный (копируемый) массив; индекс в исходном массиве, с которого будет начинаться копирование; третий параметр — конечный индекс до которого будут копироваться элементы (значение под этим индексом не включается в копирование).
Еще пример. Необходимо найти максимальное число, затем скопировать в новый массив все значения, которые находятся справа от этого числа, включая само число:
import java.util.Arrays; public class Main < public static void main(String[] args) < double[] srcArr = ; double max = srcArr[0]; int maxNumIndex = 0; for (int i = 1; i < srcArr.length; i++) < if (srcArr[i] >max) < maxNumIndex = i; max = srcArr[i]; >> double[] destArr = Arrays.copyOfRange(srcArr, maxNumIndex, srcArr.length); System.out.println(Arrays.toString(destArr)); > >
Метод copyOfRange(), так же как и copyOf(), если количество копируемых элементов указано больше, чем их содержит массив, дополняет итоговый массив значениями по умолчанию.
В Java есть еще один способ скопировать массив — с помощью нативного (native) метода arraycopy(), расположенного в классе System.
Его работа имеет принципиальное отличие от копирования элементов массива в цикле: он копирует не поэлементно, а целыми блоками памяти, что влияет положительно на производительность.
Данный класс находится в пакете java.lang, и его не нужно импортировать — это делается автоматически.
Нативными называются методы, реализация которых написана на каком-то другом языке, отличном от Java (например, С/C++), под конкретную ОС, что делает их код платформозависимым, т. е. «родным» для конкретной системы.
Получается, что сигнатуру метода arraycopy() с ключевым словом native мы можем наблюдать в классе System, а вот реализация, написанная на языках C/C++, находится совсем в другом месте. Она является частью скомпилированной в виде машинного (бинарного) кода библиотеки внутри JVM.
@IntrinsicCandidate public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
Запомнить последовательность аргументов, которые принимает метод, не сложно. Рассуждать можно следующим образом: из исходного массива (src), начиная с начальной позиции (srcPos), нужно скопировать данные в другой массив (dest), в такую-то позицию (destPos), в таком-то количестве (length).
Обратите внимание, что оба массива имеют тип Object. Это сделано для универсальности, чтобы данный метод мог работать с массивами любого типа.
Над сигнатурой метода мы также можем наблюдать аннотацию @IntrinsicCandidate (до Java 16 она называлась @HotSpotIntrinsicCandidate), сообщающую о том, что JVM вместо вызова кода, написанного на другом языке (а такие вызовы могут негативно влиять на производительность и делают невозможным выполнять оптимизации кода), может использовать внутреннюю (встроенную) реализацию данного метода, которая есть у JIT (Just-in-Time — технология увеличения производительности программ за счет компиляции часто используемых частей кода).
В режиме интерпретатора (когда JVM выполняет вашу программу байт-код за байт-кодом) виртуальной машиной будет запускаться native-версия arraycopy(), но проработав какое-то время и собрав статистику, при определенных условиях она будет рассматривать методы с подобными аннотациями как кандидаты на замену native-кода внутренним машинным кодом.
Разберем пример работы с arraycopy(). Пусть требуется удалить значение по индексу 0, а затем сдвинуть влево все числа, стоящие от него справа:
import java.util.Arrays; class Main < public static void main(String[] args) < int[] arr = ; System.arraycopy(arr, 1, arr, 0, arr.length - 1); System.out.println(Arrays.toString(arr)); arr[arr.length - 1] = 0; System.out.println(Arrays.toString(arr)); > >
Массивы, обработка элементов массива
Представьте себе такую задачу. Вам нужно хранить в памяти компьютера значения линейной функции при . Как это сделать? Мы умеем создавать отдельные переменные, но тогда здесь нам понадобится 100 переменных, с которыми надо будет еще как-то управляться. Но, к счастью, все можно сделать гораздо проще. Можно задать массив из 100 элементов и в каждый элемент массива записать значение функции при конкретном значении x.
Итак, чтобы задать массив в языке Java используется такой синтаксис:
Например, в нашем случае следует выбрать вещественный тип данных для элементов массива. Имя массива обозначим как и функцию y:
и далее можем создать массив со 100 элементами с помощью оператора new:
Эти две строчки можно объединить в одну и записать все так:
Все, мы создали массив. Теперь, чтобы в его первый элемент записать первое значение функции, используется такой синтаксис:
Здесь k, b – переменные с какими-либо значениями, а x=0. Обратите внимание, первый элемент массива всегда имеет индекс, равный нулю. По аналогии, записывается значение во второй элемент массива:
и так далее. Давайте напишем целиком программу, которая заносит все 100 значений в массив и выводит их на экран.
Обратите внимание, если мы хотим прочитать значение из массива, то достаточно просто обратиться к нему по соответствующему индексу, например, так:
В результате переменная a будет равна 6-му значению элемента массива y. Поэтому, когда мы пишем
то осуществляется вывод элемента массива с индексом x. Вот так можно записывать и считывать значения из массива.
В языке Java можно сразу инициализировать массив конкретными значениями в момент его объявления, например, так:
int powers[] = new int[] {1, 2, 4, 6};
В этом случае элементу powers[0] присваивается значение 1, powers[1] – 2, и т.д. Обратите внимание, что в этом случае нигде не должен указываться размер массива. Его размер определяется числом инициализируемых элементов.
Выведем этот массив в консоль:
Смотрите, здесь для определения числа элементов в массиве использовалось его свойство length. То есть, индекс последнего элемента в массиве всегда равен length-1. Например, вывести только последний элемент нашего массива можно так:
System.out.println(powers[powers.length-1]);
Для хранения некоторых видов информации, например, изображений удобно пользоваться двумерными массивами. Объявление двумерных массивов осуществляется следующим образом:
int ar2D[][] = new int[3][4]; int array2D[][] = { { 0, 1, 2 }, { 3, 4, 5 } };
Какой индекс здесь считать строками, а какой – столбцами, решает сам программист, компьютер все равно будет обрабатывать элементы этого массива в соответствии с программой и что такое строки и столбцы ему неведомо.
Здесь также, первый элемент массива имеет индексы 0, то есть,
array2D[0][0] = 1; //в первый элемент записано число 1
array2D[0][1] = 2; array2D[1][0] = 3;
и так далее. Давайте в качестве примера напишем программу, которая бы записывала в массив E размерностью 10×10 такие значения:
final int N = 10; int E[][] = new int[N][N]; for(int i = 0;i N;++i) for(int j = 0;j N;++j) if(i == j) E[i][j] = 1; else E[i][j] = 0; for (int i = 0; i N; ++i) { for (int j = 0; j N; ++j) System.out.print(E[i][j]+" "); System.out.print("\n"); }
Также в Java можно создавать так называемые многомерные зубчатые массивы. Визуально такой двумерный массив можно представить вот в таком виде:
short z[][] = new short[5][]; z[0] = new short[3]; z[1] = new short[4]; z[2] = new short[2]; z[3] = new short[3]; z[4] = new short[1];
Для обработки элементов такого массива можно записать такие циклы:
short cnt = 1; for(int i = 0;i z.length;++i) for(int j = 0;j z[i].length;++j) { z[i][j] = cnt; cnt++; } for(int i = 0;i z.length;++i) { for (short val : z[i]) System.out.print(val + " "); System.out.print("\n"); }
Смотрите, что здесь получается. Вот это свойство z.length возвращает первую размерность массива, то есть 5. Далее, мы берем i-ю строку (либо столбец в зависимости от интерпретации) и узнаем сколько элементов в этой строке. И внутри второго цикла записываем туда значение cnt, которое постоянно увеличивается на 1.
Затем, мы выводим полученный массив в консоль. Здесь также сначала перебираем первую его размерность. А вот этот цикл перебирает по порядку все элементы i-й строки и помещает их в переменную val. Обратите внимание на его синтаксис:
Вот так можно перебирать элементы любой коллекции, в данном случае строки массива. Вот так все это работает. По аналогии можно задавать массивы любой размерности.
Обработка элементов массива
- Удаление значения из массива по определенному индексу.
- Вставка значения в массив по определенному индексу.
- Сортировка элементов массива.
final int N = 9; short a[] = new short[N];
for(int i=0;i N;++i) a[i] = (short)(i+1);
Теперь удалим элемент со значением 6. Для этого нужно проделать такую операцию: Причем, сначала перемещаем 7-ку на место 6-ку, затем 8-ку и 9-ку, то есть, двигаемся от удаляемого элемента к концу массива. Программа будет выглядеть так:
Здесь мы начали движение с 5-го индекса (то есть 6-го элемента массива) и на первой итерации делаем операцию a[5]=a[6], то есть, 7-ку ставим на место 6-ки. На следующей итерации уже имеем a[6]=a[7] – перемещаем 8-ку и, затем, a[7]=a[8] – перемещаем 9-ку. Все, в итоге значение 6 было удалено из массива. Теперь реализуем второй алгоритм и вставим значение 4, которого не хватает вот в таком массиве:
short a[] = new short[] {1, 2, 3, 5, 6, 7, 8, 9, 9};
Здесь в конце записаны две 9, чтобы мы могли сдвинуть все элементы на 1 вправо и вставить элемент со значением 4. То есть, нам следует выполнить такую операцию над элементами массива: Обратите внимание, что сдвиг осуществляется с конца массива. Если мы начнем это делать с 4-го, то просто затрем все остальные значения пятеркой. Итак, вот программа, которая вставляет 4-ку в этот массив:
Здесь счетчик i в цикле сначала равен 8 – это индекс последнего элемента нашего массива. Затем, делается операция a[i]=a[i-1], то есть, a[8]=a[7]. Таким образом, мы присваиваем 8-му элементу значение 7-го элемента. Это и есть смещение значения вправо. На следующей итерации i уменьшается на 1, то есть, равно 7 и операция повторяется: a[7]=a[6] и так далее, последний смещаемый элемент будет: a[4]=a[3]. После этого i будет равно 3, условие цикла становится ложным и он завершается. После смещения, мы присваиваем 4-му элементу массива значение 4 и выводим получившийся массив на экран. Теперь рассмотрим довольно распространенный алгоритм сортировки элементов массива по методу всплывающего пузырька. Реализуем его на языке Java.
Здесь первый цикл показывает с какого элемента искать минимальный, то есть, это местоположение той вертикальной черты в методе всплывающего пузырька. Затем, задаем две вспомогательные переменные min – минимальное найденное значение, pos – индекс минимального элемента в массиве. Второй вложенный цикл перебирает все последующие элементы массива и сравнивает его с текущим минимальным и если будет найдено меньшее значение, то min становится равной ему и запоминается его позиция. Вот эти три строчки меняют местами текущее значение элемента с найденным минимальным, используя вспомогательную переменную t. И в конце программы выполняется вывод элементов массива на экран. Запустим эту программу и посмотрим как она работает. Кстати, если мы теперь хотим выполнить сортировку по убыванию, то достаточно изменить вот этот знак на противоположный.