Сделать копию массива - PullRequest
       15

Сделать копию массива

319 голосов
/ 26 апреля 2011

У меня есть массив a, который постоянно обновляется.Допустим, a = [1,2,3,4,5].Мне нужно сделать точную копию a и назвать ее b.Если a изменить на [6,7,8,9,10], b все равно будет [1,2,3,4,5].Каков наилучший способ сделать это?Я пробовал цикл for, например:

for(int i=0; i<5; i++) {
    b[i]=a[i]
}

, но, похоже, он работает неправильно.Пожалуйста, не используйте сложные термины, такие как глубокий текст и т. Д., Потому что я не знаю, что это значит.

Ответы [ 10 ]

530 голосов
/ 26 апреля 2011

Вы можете попробовать использовать System.arraycopy ()

int[] src  = new int[]{1,2,3,4,5};
int[] dest = new int[5];

System.arraycopy( src, 0, dest, 0, src.length );
219 голосов
/ 26 апреля 2011

Вы также можете использовать

int[] a = new int[]{1,2,3,4,5};
int[] b = a.clone();

.

169 голосов
/ 12 апреля 2013

Если вы хотите сделать копию:

int[] a = {1,2,3,4,5};

Это путь:

int[] b = Arrays.copyOf(a, a.length);

Arrays.copyOf может быть быстрее, чем a.clone() на небольших массивах,Оба элемента копируются одинаково быстро, но clone () возвращает Object, поэтому компилятор должен вставить неявное приведение к int[].Вы можете увидеть это в байт-коде, что-то вроде этого:

ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
50 голосов
/ 09 апреля 2016

Хорошее объяснение от http://www.journaldev.com/753/how-to-copy-arrays-in-java

Методы копирования массива Java

Object.clone () : Класс Object предоставляет метод clone (), и поскольку массив в java также является объектом, вы можете использовать этот метод для получения полной копии массива.Этот метод не подойдет вам, если вы хотите частичное копирование массива.

System.arraycopy () : Системный класс arraycopy () - лучший способ сделать частичное копирование массива.Он предоставляет вам простой способ указать общее количество элементов для копирования и позиции индекса исходного и конечного массивов.Например, System.arraycopy (source, 3, destination, 2, 5) скопирует 5 элементов из источника в место назначения, начиная с 3-го индекса источника до 2-го индекса назначения.

Arrays.copyOf (): Если вы хотите скопировать первые несколько элементов массива или полную копию массива, вы можете использовать этот метод.Очевидно, что он не универсален, как System.arraycopy (), но он также не сбивает с толку и прост в использовании.

Arrays.copyOfRange () : если вы хотите, чтобы копировалось несколько элементов массива,где начальный индекс не равен 0, вы можете использовать этот метод для копирования частичного массива.

31 голосов
/ 26 апреля 2011

У меня такое ощущение, что все эти "лучшие способы скопировать массив" на самом деле не решат вашу проблему.

Вы говорите

Я пробовал цикл for наподобие [...], но, похоже, он работает неправильно?

Глядя на этот цикл, нет очевидных причин , чтобы он не работал ... если только:

  • у вас каким-то образом перепутаны массивы a и b (например, a и b относятся к одному и тому же массиву), или
  • ваше приложение является многопоточным, и разные потоки одновременно читают и обновляют массив a.

В любом случае альтернативные способы копирования не решат основную проблему.

Исправление для первого сценария очевидно. Для второго сценария вам нужно найти способ синхронизации потоков. Классы атомарных массивов не помогают, потому что у них нет конструкторов атомарных копий или методов клонирования, но синхронизация с использованием примитивного мьютекса поможет.

(В вашем вопросе есть подсказки, которые заставляют меня думать, что это действительно связано с ветками; например, ваше утверждение о том, что a постоянно меняется.)

10 голосов
/ 08 апреля 2017

Вы можете попробовать использовать Arrays.copyOf () в Java

int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
7 голосов
/ 18 января 2016

Вы также можете использовать Arrays.copyOfRange.

Пример

public static void main(String[] args) {
    int[] a = {1,2,3};
    int[] b = Arrays.copyOfRange(a, 0, a.length);
    a[0] = 5;
    System.out.println(Arrays.toString(a)); // [5,2,3]
    System.out.println(Arrays.toString(b)); // [1,2,3]
}

Этот метод похож на Arrays.copyOf, но он более гибкий. Оба они используют System.arraycopy под капотом.

См

7 голосов
/ 14 ноября 2013

Все решения, которые вызывают длину из массива, добавляют ваш пример избыточного кода проверки нуля:

int[] a = {1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
int[] c = a.clone();

//What if array a comes as local parameter? You need to use null check:

public void someMethod(int[] a) {
    if (a!=null) {
        int[] b = Arrays.copyOf(a, a.length);
        int[] c = a.clone();
    }
}

Я рекомендую вам не изобретать колесо и использовать служебный класс, где все необходимые проверки уже выполнены.Рассмотрим ArrayUtils из Apache Commons.Ваш код становится короче:

public void someMethod(int[] a) {
    int[] b = ArrayUtils.clone(a);
}

Общие Apache вы можете найти там

1 голос
/ 22 августа 2017

Если вам нужно работать с необработанными массивами, а не с ArrayList, тогда Arrays имеет то, что вам нужно.Если вы посмотрите на исходный код, это самый лучший способ получить копию массива.У них действительно есть немного защитного программирования, потому что метод System.arraycopy() выдает множество непроверенных исключений, если вы передаете ему нелогичные параметры.

Вы можете использовать либо Arrays.copyOf(), который будет копироваться изпервый элемент Nth в новый более короткий массив.

public static <T> T[] copyOf(T[] original, int newLength)

Копирует указанный массив, обрезая или дополняя нулями (при необходимости), чтобы копия имела указанную длину.Для всех индексов, которые действительны как в исходном массиве, так и в копии, эти два массива будут содержать одинаковые значения.Для любых индексов, которые действительны в копии, но не в оригинале, копия будет содержать ноль.Такие индексы будут существовать тогда и только тогда, когда указанная длина больше, чем у исходного массива.Полученный массив имеет тот же класс, что и исходный массив.

2770
2771    public static <T,U> T[] More ...copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
2772        T[] copy = ((Object)newType == (Object)Object[].class)
2773            ? (T[]) new Object[newLength]
2774            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
2775        System.arraycopy(original, 0, copy, 0,
2776                         Math.min(original.length, newLength));
2777        return copy;
2778    }

или Arrays.copyOfRange() также выполнят свою задачу:

public static <T> T[] copyOfRange(T[] original, int from, int to)

Копируетуказанный диапазон указанного массива в новый массив.Начальный индекс диапазона (от) должен лежать между нулем и оригинальной длиной, включительно.Значение в оригинале [из] помещается в начальный элемент копии (кроме случаев, когда == original.length или от == до).Значения из последующих элементов в исходном массиве помещаются в последующие элементы в копии.Конечный индекс диапазона (до), который должен быть больше или равен от, может быть больше, чем original.length, и в этом случае значение null помещается во все элементы копии, индекс которых больше или равен оригиналу.длина - от.Длина возвращаемого массива будет до - от.Получившийся массив имеет тот же класс, что и исходный массив.

3035    public static <T,U> T[] More ...copyOfRange(U[] original, int from, int to, Class<? extends T[]> newType) {
3036        int newLength = to - from;
3037        if (newLength < 0)
3038            throw new IllegalArgumentException(from + " > " + to);
3039        T[] copy = ((Object)newType == (Object)Object[].class)
3040            ? (T[]) new Object[newLength]
3041            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
3042        System.arraycopy(original, from, copy, 0,
3043                         Math.min(original.length - from, newLength));
3044        return copy;
3045    }

Как вы можете видеть, обе эти функции являются просто функциями-оболочками над System.arraycopy с защитной логикой, чем то, что вы пытаетесьdo действителен.

System.arraycopy - это самый быстрый способ копирования массивов.

0 голосов
/ 14 июня 2017

Для нулевой безопасной копии массива вы также можете использовать необязательный метод с Object.clone(), предоставленным в этом ответе .

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...