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

У меня есть массив, который постоянно обновляется. 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]
}

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

Ответ 1

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

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

System.arraycopy( src, 0, dest, 0, src.length );

Ответ 2

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

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

.

Ответ 3

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

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

Ответ 4

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

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

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

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

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

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

Ответ 5

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

Вы говорите

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

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

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

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

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

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

Ответ 6

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

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. Вы становитесь короче:

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

В Apache вы можете найти там

Ответ 7

Вы также можете использовать 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 под капотом.

См

Ответ 8

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

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

Ответ 9

Если вы должны работать с необработанными массивами, а не 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)

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

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 с защитной логикой, что то, что вы пытаетесь сделать, действительно.

System.arraycopy является самым быстрым способом копирования массивов.

Ответ 10

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

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);