黑马程序员——Java基础---深层拷贝(数组、ArrayList)

——- android培训java培训、期待与您交流! ———-

JAVA中复制数组元素值:(深拷贝)

在JAVA里面,可以用复制语句“A=B”给基本类型的数据传递值,但是如果A,B是两个同类型的数组,复制就相当于将一个数组变量的引用传递给另一个数组;如果一个数组发生改变,那么引用同一数组的变量也要发生改变。

    public static void main(String[] args) {
        int[] a={3,1,4,2,5};
        int[] b=a;
        b[0]=10;
        System.out.println(b+"  "+a);
        System.out.println(b==a);
        System.out.println(b[0]+"  "+a[0]);
    }
    //结果: [I@15db9742  [I@15db9742
    //      true
    //      10  10 

为此就需要新建一个数组,而不单单是复制引用

1、使用FOR循环,将数组的每个元素复制
(当底层不是基本数据类型时:需要将每个对象调用clone方法,才能实现真正的复制)

    public static void main(String[] args) {
        int[] a={3,1,4,2,5};
        int[] b=new int[a.length];
        for(int x=0;x<a.length;x++){
            b[x]=a[x];
        }
        b[0]=10;
        System.out.println(b[0]+"  "+a[0]);
//输出 : 10  3
        int[][] a2={{3,1,4,2,5},{4,2}};
        int[][] b2=new int[a2.length][a2[0].length];
        for(int x=0;x<a2.length;x++){
            b2[x]=a2[x];
        }
        b2[0][0]=10;
        System.out.println(b2[0][0]+"  "+a2[0][0]);
    }
// 输出: 10  10
/*
        int[][] a2={{3,1,4,2,5},{4,2}};
        int[][] b2=new int[a2.length][a2[0].length];
        for(int x=0;x<a2.length;x++){
            b2[x]=a2[x].clone();
        }
        b2[0][0]=10;
        System.out.println(b2[0][0]+"  "+a2[0][0]);
//      输出:10   3
*/

2、使用clone方法,得到数组的值,而不是引用

/*
        int[] a={3,1,4,2,5};
        int[] b=a.clone();
        b[0]=10;
        System.out.println(b[0]+"  "+a[0]);
//      输出:10   3
*/

3、使用System.arraycopy(s,start1,t,start2,length)方法

    public static void main(String[] args) {
        int[] a={3,1,4,2,5};
        int[] b=new int[a.length];
        System.arraycopy(a, 0, b, 0, a.length);
        b[0]=10;
        System.out.println(b[0]+"  "+a[0]);
//      输出:10   3       
    }
/*
注:
s是原数组,t是目标数组,start1&start2是开始复制下标,length一般是s的长度,
由于arraycopy方法不给目标数组分配内存空间,所以必需要先为t分配内存空间!
*/

注意:

1.上面方法中arraycopy效率较高。

2. 以上方法,只限一维数组,多维数组,要具体到一维复制才能实现复制数组元素的值。

3. clone 和 arraycopy对二维数组进行复制时,是浅拷贝

JAVA中复制集合元素值:(深拷贝)

// 为了验证方便,这里不再覆盖 toString() 方法
public class FuZhi {

    public static void main(String[] args) {
        Student c = new Student("zhan",22);
        Student d = new Student("zhan",22);
        Student e = new Student("zhan",22);
        Student f = new Student("zhan",22);
        List<Student> li = new ArrayList<Student>();
        li.add(c);
        li.add(e);
        li.add(d);
        li.add(f);
        List<Student> li2 = new ArrayList<Student>();
        li2=li;
        li.set(0, new Student("wang",23));
// 结果1 System.out.println(li2.toString());

        System.out.println("li[0]:\t"+li.get(0)
                            +"\r\nli2[0]\t"+li2.get(0)
            +"\r\n是否相等:"+(li2.get(0)==li.get(0)));

    }

}
class Student{
    private String name;
    private int age;
    Student(String name, int age){
        this.name=name;
        this.age =age;
    }
//  public String toString(){   //结果1
//      return name+" "+age;
//  }
}
/*
输出结果1、:
[wang 23, zhan 22, zhan 22, zhan 22]
输出结果2、:
li[0]:  Hello.Student@15db9742 
li2[0]: Hello.Student@15db9742
是否相等:true
*/

ArryList()深层拷贝方法.

1、 最简洁的 new ArrayList( src)

public class FuZhi {

    public static void main(String[] args) {
        Student c = new Student("zhan",22);
        Student d = new Student("zhan",22);
        Student e = new Student("zhan",22);
        Student f = new Student("zhan",22);
        List<Student> li = new ArrayList<Student>();
        li.add(c);
        li.add(e);
        li.add(d);
        li.add(f);
        List<Student> li2 = new ArrayList<Student>();
        //  建立一个集合副本 ,复制内部所有元素
        li2 =new ArrayList<Student>(li);
        li.set(0, new Student("wang",23));
        System.out.println("li[0]:\t"+li.get(0)+"\r\nli2[0]\t"
                            +li2.get(0)+"\r\n是否相等:"
                            +(li2.get(0)==li.get(0)));
    }

}
class Student {
    private String name;
    private int age;
    Student(String name, int age){
        this.name=name;
        this.age =age;
    }
    public String toString(){
        return name+" "+age;
    }
}
/*
li[0]:  wang 23
li2[0]  zhan 22
是否相等:false
*/

2、 覆盖 clone(不建议)
通过覆盖 Object 中的 clone(),进行复制
不过只限一维,多维需要多层覆盖,很麻烦

import java.util.ArrayList;
// 首先类 必须实现 Cloneable 接口
public class TestClone implements Cloneable {
    private ArrayList<String> arrayList = new ArrayList<String>();
  // 第二 最高权限覆写 clone() 方法
    public TestClone clone() {
        TestClone testClone = null;
        try {
            testClone = (TestClone) super.clone();
            testClone.arrayList = 
            (ArrayList<String>) this.arrayList.clone();
        } catch (CloneNotSupportedException e) {
            e.printStackTrace();
        }
        return testClone;
    }
    public ArrayList<String> getArrayList() {
        return this.arrayList;
    }
    public void setValue(String value) {
        arrayList.add(value);
    }
    public static void main(String[] args) {
        TestClone testClone = new TestClone();
        testClone.setValue("张三"); 
        //调用 clone 方法
        TestClone testClone1 = testClone.clone();
        testClone1.setValue("李四");
        System.out.println(testClone.getArrayList());
        System.out.println(testClone1.getArrayList());
    }
}
/*
运行结果:
        [张三]
        [张三, 李四]
*/

3、通过序列化

就是把ArrayList的原来的对象进行序列化,然后通过反序列化读取出来,就可以了。
当然,记着放到集合中的元素也要能够序列化,所以必须实现Serializable接口。

package test;   

import java.io.Serializable;   
// 实现序列化需要实现接口 Serializable 
public class Userinfo implements Serializable    
{   
    private int id;   
    private String name;   
    public int getId() {   
        return id;   
    }   
    public void setId(int id) {   
        this.id = id;   
    }   
    public String getName() {   
        return name;   
    }   
    public void setName(String name) {   
        this.name = name;   
    }   

}  

// 下面是测试:

import java.io.ByteArrayInputStream;   
import java.io.ByteArrayOutputStream;   
import java.io.IOException;   
import java.io.ObjectInputStream;   
import java.io.ObjectOutputStream;   
import java.util.ArrayList;   
import java.util.List;   

public class TestMain {   

    /**  
     * @param args  
     */  
    public static void main(String[] args) {     
        List src = new ArrayList(2);   
        Userinfo ui1 = new Userinfo();   
        ui1.setId(1);   
        ui1.setName("aaa");   
        src.add(ui1);   

        Userinfo ui2 = new Userinfo();   
        ui1.setId(2);   
        ui1.setName("bbb");   
        src.add(ui2);   

        List dest = new ArrayList(2);   

        TestMain test = new TestMain();   

        try {   
            dest = test.deepCopy(src);   
        } catch (IOException e) {    
            e.printStackTrace();   
        } catch (ClassNotFoundException e) {   
            e.printStackTrace();   
        }   


        System.out.println(src==dest);   
        Userinfo u = (Userinfo)src.get(0);   
        Userinfo uu = (Userinfo)dest.get(0);   
        uu.setName("dkkdkddk");   
        System.out.println(u.getName());   

        System.out.println(uu.getName());   

    }   
  // 复制代码
    public List deepCopy(List src) throws IOException, ClassNotFoundException{   
        ByteArrayOutputStream byteOut = new ByteArrayOutputStream();   
        ObjectOutputStream out = new ObjectOutputStream(byteOut);   
        out.writeObject(src);   

        ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());   
        ObjectInputStream in =new ObjectInputStream(byteIn);   
        List dest = (List)in.readObject();   
        return dest;   
    }   
}

/*
输出结果:
        false
        bbb
        ccc
*/

——- android培训java培训、期待与您交流! ———-

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值