最近看线性表、栈、队列数据结构实现源码时,经常看到 Arrays.copy()、System.arraycopy() 方法。
在JDK 6中,Arrays 类别 新增了copyOf()方法. Array.copyOf() 用于复制指定的数组内容以达到扩容的目的,该方法对不同的基本数据类型都有对应的重载方法,详见 java api:
public static T[] copyOf(T[] original, int newLength) {
return (T[]) copyOf(original, newLength, original.getClass());
}
public static T[] copyOf(U[] original, int newLength, Class extends T[]> newType) {
T[] copy = ((Object)newType == (Object)Object[].class)
? (T[]) new Object[newLength]
: (T[]) Array.newInstance(newType.getComponentType(), newLength);
System.arraycopy(original, 0, copy, 0,
Math.min(original.length, newLength));
return copy;
}
从代码可知,数组拷贝时调用的是本地方法 System.arraycopy() ;
Arrays.copyOf()方法返回的数组是新的数组对象,原数组对象仍是原数组对象,不变,该拷贝不会影响原来的数组。copyOf()的第二个自变量指定要建立的新数组长度,如果新数组的长度超过原数组的长度,则保留数组默认值.
import java.util.Arrays;
public class ArrayDemo {
public static void main(String[] args) {
int[] arr1=new int[]{2,5,6,0,0,0};
int[] arr2=new int[]{1,3,4};
// Object src, int srcPos,
// Object dest, int destPos,
// int length
System.arraycopy(arr2,0,arr1,arr2.length,arr2.length);
Arrays.sort(arr1);
System.out.println(Arrays.toString(arr1));
}
}
输出: [1, 2, 3, 4, 5, 6]
public static native void arraycopy(Object src, int srcPos,
Object dest, int destPos,
int length);
参数说明:
src:源对象
srcPos:源数组中的起始位置
dest:目标数组对象
destPos:目标数据中的起始位置
length:要拷贝的数组元素的数量
System.arraycopy() 源码如下:
public class ArraycopyTest{
public static void main(String[] args){
char[] c1 = new String("123456").toCharArray();
char[] c2 = new String("abcdef").toCharArray();
System.arraycopy(c1, 2, c2, 1, 2);
System.err.println(Arrays.toString(c1));
System.err.println(Arrays.toString(c2));
}
}
输出: [1, 2, 3, 4, 5, 6]
[a, 3, 4, d, e, f]
1> 普通增加
public boolean add(E e) {
ensureCapacityInternal(size + 1); // Increments modCount!!
elementData[size++] = e;
return true;
}
2> 指定位置添加
public void add(int index, E element) {
rangeCheckForAdd(index);
ensureCapacityInternal(size + 1); // Increments modCount!!
System.arraycopy(elementData, index, elementData, index + 1,
size - index);
elementData[index] = element;
size++;
}
在index=2的位置添加新元素
3> 删除指定位置元素
public E remove(int index) {
rangeCheck(index);
modCount++;
E oldValue = elementData(index);
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
return oldValue;
}
4> 删除指定元素 (和上面删除指定索引的实现是一样的)
注意: 如果要删除的元素在集合中有多个 那么不能全删除掉,此时应该使用倒序遍历删除
public boolean remove(Object o) {
if (o == null) {
for (int index = 0; index < size; index++)
if (elementData[index] == null) {
fastRemove(index);
return true;
}
} else {
for (int index = 0; index < size; index++)
if (o.equals(elementData[index])) {
fastRemove(index);
return true;
}
}
return false;
}
/*
* Private remove method that skips bounds checking and does not
* return the value removed.
*/
private void fastRemove(int index) {
modCount++;
int numMoved = size - index - 1;
if (numMoved > 0)
System.arraycopy(elementData, index+1, elementData, index,
numMoved);
elementData[--size] = null; // clear to let GC do its work
}