- Как скопировать массив в Java? Копирование массивов
- Методы для копирования массивов в Java
- Скопируйте массив объектов в Java
- 1. Использование System.arraycopy() метод
- 2. Использование Object.clone() метод
- 3. Использование Arrays.copyOf() метод
- 4. Использование Arrays.copyOfRange() метод
- 5. Сериализация массива объектов с помощью GSON
- Java глубокая копия массива
Как скопировать массив в Java? Копирование массивов
В статье поговорим о некоторых методах копирования массивов в Java. Этот язык программирования имеет встроенные методы, предназначенные для решения данных задач. С их помощью вы сможете сделать как полную копию массива, так и выполнить копирование некоторых элементов массива.
Методы для копирования массивов в Java
В Java существует довольно много специальных методов для копирования массивов:
1.В первую очередь, хотелось бы упомянуть Object.clone() — этот метод вы можете использовать для полного копирования массива. Соответственно, если вы хотите скопировать массив частично, этот способ вам не подойдёт.
2.Следующий на очереди — System.arraycopy() — по сути, это один из наилучших способов создать частичную копию массива в Java. В этом методе определены следующие параметры: — массив, элементы которого планируем копировать; — индекс элемента; — итоговый (результирующий) массив; — первый элемент итогового массива; — общее число элементов, предназначенных для копирования.
К примеру, написав System.arraycopy(источник, 2, назначения, 5, 7), вы скопируете семь элементов из массива-источника в итоговый массив, начиная со второго индекса источника в пятый индекс результирующего массива.
3. Arrays.copyOf() — подойдёт вам, если планируете выполнить копирование нескольких первых элементов массива либо сделать полную копию массива. Способ не так универсален, как System.arraycopy() , но так же прост в применении.
4. Arrays.copyOfRange() — полезный метод, обеспечивающий частичное копирование массива.
В принципе, для решения большинства задач по полному либо частичному копированию массивов в Java вышеперечисленных методов вам вполне хватит. Только учтите, что методы, встроенные в Java для копирования, годятся лишь для одномерных массивов.
Пришла пора посмотреть на них в действии.
import java.util.Arrays; public class JavaArrayCopyExample < /** * В этом классе мы демонстрируем методы копирования массивов в java * @param args */ public static void main(String[] args) int[] source = ; int[] source1 = ; int[] destination=null; System.out.println("Массив-источник = " + Arrays.toString(source)); destination = copyFirstFiveFieldsOfArrayUsingSystem(source); System.out.println("Копируем первые пять элементов массива, если они есть. Итоговый массив = " + Arrays.toString(destination)); destination = copyFirstFiveFieldsOfArrayUsingSystem(source1); System.out.println("Копируем первые пять элементов массива, если они есть. Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingSystem(source); System.out.println("Осуществляем полное копирование массива посредством System.copyarray(). Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingClone(source); System.out.println("Осуществляем полное копирование массива посредством clone(). Итоговый массив = " + Arrays.toString(destination)); destination = copyFullArrayUsingArrayCopyOf(source); System.out.println("Осуществляем полное копирование массива посредством Arrays.copyOf(). Итоговый массив = " + Arrays.toString(destination)); destination = copyLastThreeUsingArrayCopyOfRange(source); System.out.println("Копируем последние три элемента массива посредством Arrays.copyOfRange(). Итоговый массив = " + Arrays.toString(destination)); > /** * Данный метод выполняет полное копирование массива посредством Arrays.copyOf() * @param source * @return */ private static int[] copyFullArrayUsingArrayCopyOf(int[] source) return Arrays.copyOf(source, source.length); > /** * Данный метод копирует последние три элемента посредством * Arrays.copyOfRange() * @param source * @return */ private static int[] copyLastThreeUsingArrayCopyOfRange(int[] source) // проверка длины для предотвращения java.lang.ArrayIndexOutOfBoundsException //но для простоты метода мы этого не делаем :) return Arrays.copyOfRange(source, source.length-3, source.length); > /** * Данный метод выполняет полное копирование массива посредством clone() * @param source * @return */ private static int[] copyFullArrayUsingClone(int[] source) return source.clone(); > /** * Данный метод выполняет полное копирование массива посредством System.arraycopy() * @param source * @return */ private static int[] copyFullArrayUsingSystem(int[] source) int[] temp=new int1; System.arraycopy(source, 0, temp, 0, source.length); return temp; > /** * Метод копирует первые пять элементов * посредством System.arraycopy() * @param source * @return */ private static int[] copyFirstFiveFieldsOfArrayUsingSystem(int[] source) < if(source.length >5)< int[] temp=new int[5]; System.arraycopy(source, 0, temp, 0, 5); return temp; >else < int[] temp=new int1; System.arraycopy(source, 0, temp, 0, source.length); return temp; >> >Теперь посмотрим на результат выполнения нашей программы:
Массив-источник = [1, 2, 3, 4, 5, 6, 7, 8, 9] Копируем первые пять элементов массива, если они есть. Итоговый массив = [1, 2, 3, 4, 5] Копируем первые пять элементов массива, если они есть. Итоговый массив = [1, 2, 3] Осуществляем полное копирование массива посредством System.copyarray(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Осуществляем полное копирование массива посредством clone(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Осуществляем полное копирование массива посредством Arrays.copyOf(). Итоговый массив = [1, 2, 3, 4, 5, 6, 7, 8, 9] Копируем последние три элемента массива посредством Arrays.copyOfRange(). Итоговый массив = [7, 8, 9]Вот и всё. Если же вы хотите получить действительно продвинутые знания по Java, приходите на наш курс:
Скопируйте массив объектов в Java
В этом посте будет обсуждаться, как скопировать массив объектов в новый массив в Java.
Мы обсудили, как скопировать примитивный массив в новый массив в Java в предыдущий пост. В этом посте мы обсудим, как мы можем скопировать массив объектов.
1. Использование System.arraycopy() метод
System.arraycopy() просто копирует массив из указанного исходного массива, начиная с указанной позиции, в указанную позицию целевого массива. Если исходный массив содержит ссылочные элементы, они также копируются.
результат:
Copied successfully: [1, 2, 3, 4, 5]
Приведенный выше код эквивалентен:
2. Использование Object.clone() метод
Мы знаем, что массивы — это объекты в Java, и все методы класса Object класс может быть вызван для массива.
Object класс имеет clone() метод для копирования объектов в Java, а поскольку массивы рассматриваются как объекты, мы можем использовать этот метод и для копирования массивов.
результат:
Copied successfully: [1, 2, 3, 4, 5]
Обратите внимание, что Object.clone() метод создает мелкая копия массива, т. е. новый массив может ссылаться на те же элементы, что и исходный массив. Для иллюстрации рассмотрим следующий пример:
результат:
Shallow copy
3. Использование Arrays.copyOf() метод
Arrays.copyOf() также может использоваться для копирования указанного массива в новый массив, как показано ниже. Если указанный массив содержит какие-либо ссылочные элементы, этот метод также выполняет поверхностное копирование.
Arrays.copyOf() имеет перегруженная версия где мы можем указать Type полученного массива.
4. Использование Arrays.copyOfRange() метод
Arrays также обеспечивает copyOfRange() метод, аналогичный copyOf() но только копирует элементы между указанным диапазоном в новый массив.
Похожий на Arrays.copyOf() , создается поверхностная копия исходного массива, а также у него есть перегруженная версия, в которой мы можем указать Type полученного массива.
5. Сериализация массива объектов с помощью GSON
Мы видели, что во всех рассмотренных выше подходах создается поверхностная копия массива, но это то, чего нам может не хотеться. Одним из простых решений этой проблемы является Serialization. Для иллюстрации следующий код возвращает глубокую копию массива путем сериализации массива с помощью библиотеки Google Gson.
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)); > >