414

I have an array a which is constantly being updated. Let's say a = [1,2,3,4,5]. I need to make an exact duplicate copy of a and call it b. If a were to change to [6,7,8,9,10], b should still be [1,2,3,4,5]. What is the best way to do this? I tried a for loop like:

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

but that doesn't seem to work correctly. Please don't use advanced terms like deep copy, etc., because I do not know what that means.

1
  • For explanation of deep copy versus shallow copy, see Wikipedia. Commented Mar 3 at 17:12

11 Answers 11

642

You can try using System.arraycopy()

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

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

But, probably better to use clone() in most cases:

int[] src = ...
int[] dest = src.clone();
9
  • 11
    +1 for not reiventing the wheel. And as far as I know it, this solution is the faster you can get in array copying. Commented Apr 26, 2011 at 4:22
  • 9
    both clone and arraycopy are native. I'd expect clone to be marginally faster. not that the difference matters. Commented Apr 26, 2011 at 4:33
  • 5
    @Felipe, @MeBigFatGuy - only for a large array. For a small array, a copy loop may be faster because of the setup overheads. If you look at the javadoc for System.arraycopy, you'll see that the method needs to check various things before it starts. Some of these checks are unnecessary with a copy loop, depending on the static array types.
    – Stephen C
    Commented Apr 26, 2011 at 4:34
  • 7
    @FelipeHummel, @MeBigFatGuy, @StephenC - Here is a performance test of the array copy methods mentioned in the answers here. In that set up, clone() turns out to be the fastest for 250 000 elements.
    – Adam
    Commented Mar 23, 2014 at 5:16
  • 29
    It's disappointing to see that all the discussion here is about micro-performance issues, which 99.999% of the time, don't matter. The more important point is that src.clone() is more readable and has far less opportunity for error than allocating a new array and doing arraycopy. (And also happens to be fast.) Commented Mar 17, 2020 at 14:03
249

you can use

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

as well.

8
  • 6
    I'm just clearing the OP's point that: "If A were to change to [6,7,8,9,10], B should still be [1,2,3,4,5]". OP said he tried using loop but doesn't worked for him.
    – Harry Joy
    Commented Apr 26, 2011 at 4:17
  • 16
    The cast is unnecessary; a good static analyzer will warn about it. But cloning is definitely the best way to make a new copy of an array.
    – erickson
    Commented Apr 26, 2011 at 4:23
  • 5
    @MeBigFatGuy - the OP's use-case entails repeated copying to the same array, so clone doesn't work.
    – Stephen C
    Commented Apr 26, 2011 at 4:36
  • 4
    @Stephen C, i didn't read that. I just read he wants a copy, and will then subsequently be repeatedly updating the non-stashed version. Commented Apr 26, 2011 at 4:41
  • 4
    @MeBigFatGuy - he said "I have an array A which is constantly being updated.". Maybe I'm reading too much into that, but I take this as implying that he is repeatedly copying A to B as well.
    – Stephen C
    Commented Apr 26, 2011 at 4:54
204

If you want to make a copy of:

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

This is the way to go:

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

Arrays.copyOf may be faster than a.clone() on small arrays. Both copy elements equally fast but clone() returns Object so the compiler has to insert an implicit cast to int[]. You can see it in the bytecode, something like this:

ALOAD 1
INVOKEVIRTUAL [I.clone ()Ljava/lang/Object;
CHECKCAST [I
ASTORE 2
0
68

Nice explanation from http://www.journaldev.com/753/how-to-copy-arrays-in-java

Java Array Copy Methods

Object.clone(): Object class provides clone() method and since array in java is also an Object, you can use this method to achieve full array copy. This method will not suit you if you want partial copy of the array.

System.arraycopy(): System class arraycopy() is the best way to do partial copy of an array. It provides you an easy way to specify the total number of elements to copy and the source and destination array index positions. For example System.arraycopy(source, 3, destination, 2, 5) will copy 5 elements from source to destination, beginning from 3rd index of source to 2nd index of destination.

Arrays.copyOf(): If you want to copy first few elements of an array or full copy of array, you can use this method. Obviously it’s not versatile like System.arraycopy() but it’s also not confusing and easy to use.

Arrays.copyOfRange(): If you want few elements of an array to be copied, where starting index is not 0, you can use this method to copy partial array.

1
  • Link in answer is dead, unfortunately - "404 Not Found".
    – Pang
    Commented Sep 26, 2023 at 5:19
37

I have a feeling that all of these "better ways to copy an array" are not really going to solve your problem.

You say

I tried a for loop like [...] but that doesn't seem to be working correctly?

Looking at that loop, there's no obvious reason for it not to work ... unless:

  • you somehow have the a and b arrays messed up (e.g. a and b refer to the same array), or
  • your application is multi-threaded and different threads are reading and updating the a array simultaneously.

In either case, alternative ways of doing the copying won't solve the underlying problem.

The fix for the first scenario is obvious. For the second scenario you will have to figure out some way of synchronizing the threads. Atomic array classes don't help because they have no atomic copy constructors or clone methods, but synchronizing using a primitive mutex will do the trick.

(There are hints in your question that lead me to think that this is indeed thread related; e.g. your statement that a is constantly changing.)

0
18

You can try using Arrays.copyOf() in Java

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

All solution that call length from array, add your code redundant null checkersconsider example:

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();
    }
}

I recommend you not inventing the wheel and use utility class where all necessary checks have already performed. Consider ArrayUtils from apache commons. You code become shorter:

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

Apache commons you can find there

9

You can also use Arrays.copyOfRange.

Example:

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]
}

This method is similar to Arrays.copyOf, but it's more flexible. Both of them use System.arraycopy under the hood.

See:

1
  • Last link in answer appears dead - "ERR_CONNECTION_TIMED_OUT".
    – Pang
    Commented Nov 9, 2023 at 5:24
4

If you must work with raw arrays and not ArrayList then Arrays has what you need. If you look at the source code, these are the absolutely best ways to get a copy of an array. They do have a good bit of defensive programming because the System.arraycopy() method throws lots of unchecked exceptions if you feed it illogical parameters.

You can use either Arrays.copyOf() which will copy from the first to Nth element to the new shorter array.

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

Copies the specified array, truncating or padding with nulls (if necessary) so the copy has the specified length. For all indices that are valid in both the original array and the copy, the two arrays will contain identical values. For any indices that are valid in the copy but not the original, the copy will contain null. Such indices will exist if and only if the specified length is greater than that of the original array. The resulting array is of exactly the same class as the original array.

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    }

or Arrays.copyOfRange() will also do the trick:

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

Copies the specified range of the specified array into a new array. The initial index of the range (from) must lie between zero and original.length, inclusive. The value at original[from] is placed into the initial element of the copy (unless from == original.length or from == to). Values from subsequent elements in the original array are placed into subsequent elements in the copy. The final index of the range (to), which must be greater than or equal to from, may be greater than original.length, in which case null is placed in all elements of the copy whose index is greater than or equal to original.length - from. The length of the returned array will be to - from. The resulting array is of exactly the same class as the original array.

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    }

As you can see, both of these are just wrapper functions over System.arraycopy with defensive logic that what you are trying to do is valid.

System.arraycopy is the absolute fastest way to copy arrays.

3

For a null-safe copy of an array, you can also use an optional with the Object.clone() method provided in this answer.

int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
2
  • 1
    Despite the fact that this solution is over complicted it also introduces memory waste and if the array contains a secret (eg. byte array with password) it also introduces security flaws because the intermediate objects will reside on the heap until garbage collection an may be exposed to attackers. Commented Jan 7, 2019 at 23:59
  • 1
    I don't agree the array will be on the heap specially for this construct. Indeed it calls clone only when needed and the Optional object is just an empty object with a reference to the existing array. About performance impact, I would say it is premature to say it is actually an impact since this type of construct is a good candidate for inlining inside the JVM and then not more impact than other methods. It's a matter of style (functional programming versus procedural programming but not only) to consider it as more complicated or not. Commented May 16, 2019 at 5:46
2

I had a similar problem with 2D arrays and ended here. I was copying the main array and changing the inner arrays' values and was surprised when the values changed in both copies. Basically both copies were independent but contained references to the same inner arrays and I had to make an array of copies of the inner arrays to get what I wanted.

This is sometimes called a deep copy. The same term "deep copy" can also have a completely different and arguably more complex meaning, which can be confusing, especially to someone not figuring out why their copied arrays don't behave as they should. It probably isn't the OP's problem, but I hope it can still be helpful.

Not the answer you're looking for? Browse other questions tagged or ask your own question.