我有一个不断更新的数组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];
}

但这似乎并不正确。请不要使用像深度复制等高级术语,因为我不知道那是什么意思。


您可以尝试使用System.arraycopy()

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

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

但是,在大多数情况下使用clone()可能更好:

int[] src = ...
int[] dest = src.clone();

你可以使用

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


我有一种感觉,所有这些“复制数组的更好方法”都不能真正解决您的问题。

你说

我尝试了一个for循环,像[…]但它似乎不能正常工作?

看看这个循环,没有明显的理由让它不起作用……除非:

你以某种方式把a和b数组弄乱了(例如,a和b指向同一个数组),或者 您的应用程序是多线程的,不同的线程同时读取和更新a数组。

在任何一种情况下,复制的其他方法都不能解决潜在的问题。

解决第一种情况的办法是显而易见的。对于第二种场景,您必须找到同步线程的方法。原子数组类没有帮助,因为它们没有原子复制构造函数或克隆方法,但是使用原语互斥量进行同步就可以了。

(你的问题中有一些暗示让我认为这确实与线程有关;例如,你说a是不断变化的。)


如果你想复制下列文件:

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

这是一条正确的道路:

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

数组。在小型数组上,copyOf可能比a.r onclone()更快。两者复制元素的速度相同,但clone()返回Object,因此编译器必须插入隐式转换为int[]。你可以在字节码中看到它,就像这样:

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

所有的解决方案,调用长度从数组,添加你的代码冗余空检查器考虑的例子:

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

我建议您不要白费力气,而是使用已经执行了所有必要检查的实用程序类。考虑一下apache commons中的ArrayUtils。你的代码变得更短:

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

你可以在那里找到Apache commons


你也可以使用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在引擎盖下。

See:

https://docs.oracle.com/javase/8/docs/api/java/util/Arrays.html https://docs.oracle.com/javase/tutorial/java/nutsandbolts/arrays.html http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/8u40-b25/java/util/Arrays.java?av=f


来自http://www.journaldev.com/753/how-to-copy-arrays-in-java的精彩解释

Java数组复制方法

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.


您可以尝试在Java中使用Arrays.copyOf()

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

对于数组的空安全副本,还可以使用可选的Object.clone()方法。

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

如果你必须使用原始数组而不是ArrayList,那么arrays可以满足你的需要。如果查看源代码,这些绝对是获取数组副本的最佳方法。它们确实有一些很好的防御性编程,因为如果您向System.arraycopy()方法提供不合逻辑的参数,它会抛出许多未检查的异常。

您可以使用Arrays.copyOf(),它将从第一个到第n个元素复制到新的较短数组。

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    }

或者Arrays.copyOfRange()也可以做到这一点:

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    }

如您所见,这两个都是系统的包装器函数。Arraycopy的防御逻辑,你试图做的是有效的。

系统。Arraycopy绝对是复制数组最快的方法。


我在2D数组中遇到了类似的问题,并在这里结束。 我复制了主数组并更改了内部数组的值,当两个副本中的值都发生变化时,我感到惊讶。基本上这两个副本都是独立的,但包含对相同内部数组的引用,我必须对内部数组做一个数组的副本来得到我想要的。

这有时被称为深度复制。同样的术语“深度复制”也可能有完全不同的、可以说更复杂的含义,这可能会令人困惑,特别是对于那些不明白为什么他们复制的数组没有按照应有的方式运行的人来说。这可能不是OP的问题,但我希望它仍然能有所帮助。