Answers:
您可以尝试使用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();
System.arraycopy
,您将看到该方法需要在启动之前检查各种情况。这些检查中的某些检查对于复制循环而言是不必要的,具体取决于静态数组类型。
src.clone()
与分配新数组并执行操作相比,此方法更具可读性,并且出错的机会要少得多arraycopy
。(而且碰巧也很快。)
您可以使用
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[]
。您可以在字节码中看到它,如下所示:
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)将5个元素从源复制到目标,从源的第三个索引复制到目标的第二个索引。
Arrays.copyOf():如果要复制数组的前几个元素或数组的完整副本,则可以使用此方法。显然,它不像System.arraycopy()那样通用,但也不易混淆且易于使用。
Arrays.copyOfRange():如果要复制数组的几个元素(起始索引不为0),则可以使用此方法复制部分数组。
我觉得所有这些“复制数组的更好方法”并不能真正解决您的问题。
你说
我尝试了类似[...]的for循环,但似乎无法正常工作?
查看该循环,没有明显的理由使其不起作用...除非:
a
and b
数组弄乱了(例如,a
并b
引用相同的数组),或者a
同时读取和更新数组。无论哪种情况,执行复制的其他方式都无法解决潜在的问题。
第一种情况的解决方法很明显。对于第二种情况,您将必须找出某种同步线程的方法。原子数组类无济于事,因为它们没有原子拷贝构造函数或克隆方法,但是使用原始互斥锁进行同步将达到目的。
(您的问题中有一些提示使我认为这确实与线程相关;例如,您的声明a
一直在变化。)
您可以尝试在Java中使用Arrays.copyOf()
int[] a = new int[5]{1,2,3,4,5};
int[] b = Arrays.copyOf(a, a.length);
所有从数组调用长度的解决方案,添加您的代码多余的null checkers考虑示例:
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
在引擎盖下使用。
见:
对于数组的空安全副本,还可以Object.clone()
在此答案中提供的方法中使用可选方法。
int[] arrayToCopy = {1, 2, 3};
int[] copiedArray = Optional.ofNullable(arrayToCopy).map(int[]::clone).orElse(null);
Optional
对象只是对现有数组的引用的空对象。关于性能影响,现在说它实际上是影响还为时过早,因为这种类型的构造是在JVM内部进行内联的很好的候选者,并且其影响不比其他方法大。认为它是否更复杂是一个风格问题(函数式编程还是过程式编程,但不仅如此)。
如果您必须使用原始数组而不是原始数组,ArrayList
那么Arrays
您需要什么。如果您查看源代码,那么这是获取数组副本的绝对最佳方法。它们确实具有很好的防御性编程,因为System.arraycopy()
如果您向其提供不合逻辑的参数,该方法将引发许多未经检查的异常。
您可以使用其中任何Arrays.copyOf()
一个将第一个Nth
元素复制到新的较短数组。
public static <T> T[] copyOf(T[] original, int newLength)
复制指定的数组,截断或使用null填充(如果需要),以便副本具有指定的长度。对于在原始数组和副本中均有效的所有索引,两个数组将包含相同的值。对于副本中有效但原始索引无效的任何索引,副本将包含null。当且仅当指定长度大于原始数组的长度时,此类索引才会存在。所得数组与原始数组具有完全相同的类。
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 [from]处的值放置在副本的初始元素中(除非from == original.length或from == to)。来自原始数组中后续元素的值将放入副本中的后续元素中。范围(to)的最终索引(必须大于或等于from)可以大于original.length,在这种情况下,会将空值放在索引大于或等于原始值的副本的所有元素中。长度-从。返回数组的长度将为--from。所得数组与原始数组具有完全相同的类。
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
是复制阵列的绝对最快的方法。