一、Arrays工具类
Arrays工具类源码在java.util包里,提供的常用方法有:
- Arrays.sort 按升序进行数组排序(全部/部分)
- Arrays.binarySearch 二分搜索法搜索指定类型的数组,以查找指定的键值
- Arrays.equals 判断两个数组是否相等,返回结果为boolean类型
- Arrays.fill 填充数组(全部/部分)
- Arrays.toString / deepToString 将一维/多维以字符串形式输出
- Arrays.copyOf 复制数组
- Arrays.copyOfRange 复制指定范围的数组
二、数组拷贝方式的分类
- for
- clone
- System.arrayCopy()
- Arrays.copyOf()
1、for语句拷贝数组
定义两个数组,第二个数组的长度等于第一个数组,用for循环,从0号下标开始,把第一个数组的值依次赋给第二个数组的同号下标。
基本类型的拷贝:
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] array2 = new int[array.length];
for (int i = 0; i < array.length; i++) {
array2[i] = array[i];
}
System.out.println(Arrays.toString(array)); //原数组
System.out.println(Arrays.toString(array2)); //拷贝后的数组
array2[0] = 100; //修改数组0号下标的值
System.out.println(Arrays.toString(array)); //修改前的数组
System.out.println(Arrays.toString(array2)); //修改后的数组
}
}
执行结果:
引用类型的拷贝:
class TestArray {
private int val = 10;
public int getVal() { //获得值
return val;
}
public void setVal(int val) { //修改值
this.val = val;
}
}
public class forcopy {
public static void main(String[] args) {
TestArray[] testArrays = new TestArray[3]; //新建一个长度为3的数组testArrays
testArrays[0] = new TestArray();
testArrays[1] = new TestArray();
testArrays[2] = new TestArray();
TestArray[] testArrays2 = new TestArray[3];//新建一个长度为3的数组testArray2
for (int i = 0; i < testArrays.length; i++) {
testArrays2[i] = testArrays[i]; //用for语句拷贝数组
}
System.out.println("=====拷贝后======");
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal() + " "); //打印原数组
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " "); //打印拷贝后的数组
}
System.out.println();
System.out.println("======修改0号下标的值后======");
testArrays2[0].setVal(10000); //把克隆后数组0号下标的值改为10000
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal()+ " "); //打印原数组
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " "); //打印修改后的数组
}
}
}
执行结果:
由上面两个代码的执行结果不难看出,用for语句拷贝数组:
- 如果数组是简单类型,在修改拷贝后数组0号下标的值的时候,原数组的值不会改变
- 如果数组是引用类型(对象),在修改拷贝后数组0号下标的值的时候,原数组的值会改变
原因:
引用类型是地址,在修改的时候,引用类型地址的值会被改变,例如0号下标克隆之前的地址为100,克隆之后的地址也指向100,在修改克隆之后0号下标的值的时候,指向地址100的值也会被修改,所以原数组地址为100的值也会随之而改变。此时克隆前和克隆后两个引用类型同时指向同一个内存。
这里就要引两个概念,深拷贝和浅拷贝 - 深拷贝
- 浅拷贝:两个引用同时指向栈中的同一块内存
所以for是浅拷贝
2、clone方法拷贝数组
clone方法拷贝数组会产生新的对象
例:int [] a = {2,4,2,3,5};//定义数组a
int [] b = a.clone(); //定义数组b,把clone a后的数组存入b
源码:
凡是看到源码中有native的方法,底层都是用c/c++语言编写的,它的优点是:快!
简单类型的拷贝:
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] array2 = array.clone();
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
array2[0] = 99;
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
}
}
执行结果:
引用类型的拷贝:
class TestArray {
private int val = 10;
public int getVal() {
return val;
}
public void setVal(int val) {
this.val = val;
}
}
public class Prac {
public static void main(String[] args) {
TestArray[] testArrays = new TestArray[3];
testArrays[0] = new TestArray();
testArrays[1] = new TestArray();
testArrays[2] = new TestArray();
TestArray[] testArrays2 = testArrays.clone();
System.out.println("=====拷贝后======");
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal() + " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
System.out.println();
System.out.println("=====修改后======");
testArrays2[0].setVal(10000);
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal()+ " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
}
执行结果:
不难看出,clone()方法也属于浅拷贝。
3、System.arrayCopy()方法拷贝数组
源码:
public static native void arraycopy(Object src(源数组), int srcPos(原数组的起始位置,不一定是0号位置), Object dest(目的数组), int destPos(目的数组的起始位置), int length(拷贝的长度));
System.arrayCopy()方法底层也是用c/c++写的
简单类型拷贝:
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] array2 = new int[array.length];
System.arraycopy(array,0,array2,0,array.length);
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
array2[0] = 999;
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
}
执行结果:
引用类型的拷贝:
public static void main(String[] args) {
TestArray[] testArrays = new TestArray[3];
testArrays[0] = new TestArray();
testArrays[1] = new TestArray();
testArrays[2] = new TestArray();
TestArray[] testArrays2 = new TestArray[testArrays.length];
System.arraycopy(testArrays,0,testArrays2,0,testArrays.length);
System.out.println("=====拷贝后======");
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal() + " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
System.out.println();
System.out.println("=====修改后======");
testArrays2[0].setVal(10000);
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal()+ " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
}
执行结果:
4、Arrays.copyOf()方法拷贝数组
int[] array = {1,2,3,4,5};
int[] array2 = Arrays.copyOf(array,array.length);
Arrays.copyOf()的源码
从源码看出,Arrays.copyOf()底层是调用System.arraycopy()方法
简单类型的拷贝
public static void main(String[] args) {
int[] array = {1,2,3,4,5};
int[] array2 = Arrays.copyOf(array,array.length);
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
array2[0] = 999;
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(array2));
}
执行结果:
引用类型的拷贝
public static void main(String[] args) {
TestArray[] testArrays = new TestArray[3];
testArrays[0] = new TestArray();
testArrays[1] = new TestArray();
testArrays[2] = new TestArray();
TestArray[] testArrays2 = Arrays.copyOf(testArrays,testArrays.length);
System.out.println("=====拷贝后======");
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal() + " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
System.out.println();
System.out.println("=====修改后======");
testArrays2[0].setVal(10000);
for (int i = 0; i < testArrays.length; i++) {
System.out.print(testArrays[i].getVal()+ " ");
}
System.out.println();
for (int i = 0; i < testArrays2.length; i++) {
System.out.print(testArrays2[i].getVal()+ " ");
}
}
执行结果:
总结:
- 综上所述,数组的四种拷贝方式for /clone/ System.arrayCopy() / Arrays.copyOf()都属于浅拷贝;
- clone和system.arrayCopy()源码中有native,底层都是用c/c++写出来得
- Arrays.copyOf 底层调用的是System.arraycopy();
- clone 会产生新的对象