使数组Java的副本
我有一个不断更新的数组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 );
您可以使用
int[] a = new int[]{1,2,3,4,5}; int[] b = a.clone();
以及。
如果您想制作一份副本:
int[] a = {1,2,3,4,5};
这是要走的路:
int[] b = Arrays.copyOf(a, a.length);
Arrays.copyOf
可能比小数组上的a.clone()
更快。 两个拷贝元素同样快,但clone()返回Object
所以编译器必须向int[]
插入隐式types转换。 您可以在字节码中看到它,如下所示:
ALOAD 1 INVOKEVIRTUAL [I.clone ()Ljava/lang/Object; CHECKCAST [I ASTORE 2
尼斯的解释从http://www.journaldev.com/753/how-to-copy-arrays-in-java
Java数组复制方法
Object.clone() :Object类提供了clone()方法,并且由于java中的数组也是一个Object,所以可以使用这个方法来实现完整的数组拷贝。 如果您想要数组的部分副本,此方法将不适合您。
System.arraycopy() :系统类arraycopy()是执行数组的部分副本的最佳方法。 它为您提供了一种简单的方法来指定要复制的元素总数以及源和目标数组索引位置。 例如, System.arraycopy(source,3,destination,2,5)将从源的第3个索引开始到目的地的第2个索引从源复制5个元素。
Arrays.copyOf():如果你想复制一个数组的前几个元素或数组的完整副本,你可以使用这个方法。 显然它不是像System.arraycopy()那样的多function,但它也不会让人困惑,而且易于使用。
Arrays.copyOfRange() :如果你想要复制一个数组的几个元素,在起始索引不是0的地方,你可以使用这个方法来复制部分数组。
我有一种感觉,所有这些“更好的方法来复制一个数组”并不能真正解决你的问题。
你说
我尝试了一个循环像[…],但似乎并没有正常工作?
看着这个循环, 没有明显的原因 ,它不工作…除非:
- 你以某种方式有
a
和b
arrays搞砸了(例如a
和b
指的是相同的数组),或 - 你的应用程序是multithreading的,不同的线程同时读取和更新数组。
无论是哪种情况,复制的其他方法都不能解决潜在的问题。
第一种情况的修复很明显。 对于第二种情况,你将不得不找出一些同步线程的方法。 primefaces数组类没有帮助,因为它们没有primefaces拷贝构造函数或克隆方法,但使用原始互斥体进行同步就可以实现。
(在你的问题中有一些暗示使我认为这确实是与线程相关的;例如你的陈述a
不断变化。)
从数组中调用长度的所有解决scheme,添加您的代码冗余空值检查器例如:
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(); } }
我build议你不要发明车轮,并在所有必要的检查已经完成的情况下使用工具类。 考虑来自Apache公共的ArrayUtils。 你的代码变短了:
public void someMethod(int[] a) { int[] b = ArrayUtils.clone(a); }
你可以在那里findApache的公共资源
你也可以使用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
。
参见 :
您可以尝试在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()
方法会抛出许多未经检查的exception。
你可以使用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之间,包括0和original。 original [from]中的值被放置到副本的初始元素中(除非from == original.length或from ==)。 原始数组中后续元素的值将被放入副本中的后续元素中。 范围(to)的最后一个索引(必须大于或等于from)可能会大于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
的防御逻辑的封装函数,你所要做的是有效的。
System.arraycopy
是复制数组绝对最快的方法。