数组 list拷贝
一、目的
学习一下jdk中对于数组和list的拷贝(list扩容时需要)。
二、数组拷贝
1.使用System.arraycopy方法。
public static void copyArray(){
int[] a = new int[10];
for (int i = 0; i < 10; i++) {
a[i] = i + 1;
}
int b[] = new int[10];
System.arraycopy(a, 0, b, 0, 5);
for (int i = 0; i < 10; i++) {
System.out.print(b[i] + "\t");
}
}
运行结果如下:
2.使用Arrays.copyOf方法
public static void copyArray(){
int[] a = new int[10];
for (int i = 0; i < 10; i++) {
a[i] = i + 1;
}
int b[] = new int[10];
b = Arrays.copyOf(a, 5);
for (int i = 0; i < b.length; i++) {
System.out.print(b[i] + "\t");
}
}
运行结果如下:
注意事项:
- Arrays.copy(int[] original, int newLength)本身也只是调用了System.arraycopy(Object src, int srcPos,Object dest, int destPos, int length)。只是使用Arrays.copy(int[] original, int newLength)方法比较简单,只需传入源数组和长度即可。
- Arrays.copy(int[] original, int newLength)拷贝的数组长度取决于newLength,这一点需要注意。查看源码可以知道,创建的数组长度即为newLength,然后将此数组赋值给目标对象。
- Arrays.copy(int[] original, int newLength)拷贝的数组实际的内容最多为源数组的全部内容,其他为默认值。
源码如下:
Arrays.copy
/**
* Copies the specified array, truncating or padding with zeros (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 <tt>0</tt>.
* Such indices will exist if and only if the specified length
* is greater than that of the original array.
*
* @param original the array to be copied
* @param newLength the length of the copy to be returned
* @return a copy of the original array, truncated or padded with zeros
* to obtain the specified length
* @throws NegativeArraySizeException if <tt>newLength</tt> is negative
* @throws NullPointerException if <tt>original</tt> is null
* @since 1.6
*/
public static int[] copyOf(int[] original, int newLength) {
int[] copy = new int[newLength];
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
System.arraycope
/*
* @param src the source array.
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
* @exception IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @exception ArrayStoreException if an element in the <code>src</code>
* array could not be stored into the <code>dest</code> array
* because of a type mismatch.
* @exception NullPointerException if either <code>src</code> or
* <code>dest</code> is <code>null</code>.
*/
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
此方法是本地方法。
三、list拷贝
1.使用Collections.copy方法。
public static void copyList(){
List<String> sList = new ArrayList<>();
for (int i = 0; i < 10; i++) {
sList.add("list" + i);
}
List<String> dList = new ArrayList<>(sList);
for (int i = 0; i < 10; i++) {
dList.add(null);
}
Collections.copy(dList, sList);
for (int i = 0; i < dList.size(); i++) {
System.out.print(dList.get(i) + "\t");
}
}
注意事项:
- 使用此方法,目标list长度不能小于源list长度,否则会报错。
- 此方法应该是浅拷贝。
源码:
/**
* Copies all of the elements from one list into another. After the
* operation, the index of each copied element in the destination list
* will be identical to its index in the source list. The destination
* list must be at least as long as the source list. If it is longer, the
* remaining elements in the destination list are unaffected. <p>
*
* This method runs in linear time.
*
* @param <T> the class of the objects in the lists
* @param dest The destination list.
* @param src The source list.
* @throws IndexOutOfBoundsException if the destination list is too small
* to contain the entire source List.
* @throws UnsupportedOperationException if the destination list's
* list-iterator does not support the <tt>set</tt> operation.
*/
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}
2.使用构造方法拷贝。
源码:
/**
* Copies all of the elements from one list into another. After the
* operation, the index of each copied element in the destination list
* will be identical to its index in the source list. The destination
* list must be at least as long as the source list. If it is longer, the
* remaining elements in the destination list are unaffected. <p>
*
* This method runs in linear time.
*
* @param <T> the class of the objects in the lists
* @param dest The destination list.
* @param src The source list.
* @throws IndexOutOfBoundsException if the destination list is too small
* to contain the entire source List.
* @throws UnsupportedOperationException if the destination list's
* list-iterator does not support the <tt>set</tt> operation.
*/
public static <T> void copy(List<? super T> dest, List<? extends T> src) {
int srcSize = src.size();
if (srcSize > dest.size())
throw new IndexOutOfBoundsException("Source does not fit in dest");
if (srcSize < COPY_THRESHOLD ||
(src instanceof RandomAccess && dest instanceof RandomAccess)) {
for (int i=0; i<srcSize; i++)
dest.set(i, src.get(i));
} else {
ListIterator<? super T> di=dest.listIterator();
ListIterator<? extends T> si=src.listIterator();
for (int i=0; i<srcSize; i++) {
di.next();
di.set(si.next());
}
}
}