• List的复制 (浅拷贝与深拷贝)


    开门见山的说,List的复制其实是很常见的,List其本质就是数组,而其存储的形式是地址

     如图所示,将List A列表复制时,其实相当于A的内容复制给了B,java中相同内容的数组指向同一地址,即进行浅拷贝后A与B指向同一地址。

    造成的后果就是,改变B的同时也会改变A,因为改变B就是改变B所指向地址的内容,由于A也指向同一地址,所以A与B一起改变。

    这也就是List的浅拷贝,其常见的实现方式有如下几种:

    浅拷贝

    1、遍历循环复制

    List<Person> destList=new ArrayList<Person>(srcList.size());  
    for(Person p : srcList){  
        destList.add(p);  
    }  

    2、使用List实现类的构造方法

    List<Person> destList=new ArrayList<Person>(srcList);  

    3、使用list.addAll()方法

    List<Person> destList=new ArrayList<Person>();  
    destList.addAll(srcList);  

    4、使用System.arraycopy()方法

    Person[] srcPersons=srcList.toArray(new Person[0]);  
    Person[] destPersons=new Person[srcPersons.length];  
    System.arraycopy(srcPersons, 0, destPersons, 0, srcPersons.length);  

    测试及结果

    printList(destList); //打印未改变B之前的A 
    srcList.get(0).setAge(100);//改变B  
    printList(destList); //打印改变B后的A
    //打印结果
    123-->20  
    ABC-->21  
    abc-->22  
    123-->100  
    ABC-->21  
    abc-->22

    List 深拷贝

    如图,深拷贝就是将A复制给B的同时,给B创建新的地址,再将地址A的内容传递到地址B。ListA与ListB内容一致,但是由于所指向的地址不同,所以改变相互不受影响。

    import org.apache.commons.collections.CollectionUtils;
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    
    public class CopyTest {
    
        public static void main(String[] args) {
    
            List<Integer> list = new ArrayList<>();
            for (int i = 0; i < 10; i++) {
                list.add(i);
            }
    
            //list深度拷贝
            List<Integer> newList = new ArrayList<>();
            CollectionUtils.addAll(newList, new Object[list.size()]);
            Collections.copy(newList, list);
            newList.set(0, 10);
            
            System.out.println("原list值:" + list);
            System.out.println("新list值:" + newList);
        }
    }

    测试结果

    原list值:[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
    新list值:[10, 1, 2, 3, 4, 5, 6, 7, 8, 9]

    小结

    Java对对象和基本的数据类型的处理是不一样的。在Java中用对象的作为入口参数的传递则缺省为”引用传递”,也就是说仅仅传递了对象的一个”引用”,这个”引用”的概念同C语言中的指针引用是一样的。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。 除了在函数传值的时候是”引用传递”,在任何用”=”向对象变量赋值的时候都是”引用传递”。

    在浅复制的情况下,源数据被修改破坏之后,使用相同引用指向该数据的目标集合中的对应元素也就发生了相同的变化。因此,在需求要求必须深复制的情况下,要是使用上面提到的方法,请确保List中的T类对象是不易被外部修改和破坏的。

    
    
    
  • 相关阅读:
    谷歌Google Chrome浏览器打开新的标签页设置指定固定网址
    Vue子组件和父组件、子组件调用父组件的方法、父组件调用子组件方法、子组件与父组件间的传值
    查询Linux服务器出口IP、curl命令查询Linux公网出口IP、Windows服务器查询出口IP
    mysql查询是对字段进行补0操作,可用于树状结构整体排序
    mysql批量update更新,mybatis中批量更新操作
    CentOS 6.8下网卡配置、桥接模式和NAT连接模式、VMware虚拟机克隆网卡配置
    杂七杂八
    解决SpringMVC拦截器中Request数据只能读取一次的问题
    Redis安装教程及可视化工具RedisDesktopManager下载安装
    JAVA获取客户端请求的当前网络ip地址(附:Nginx反向代理后获取客户端请求的真实IP)
  • 原文地址:https://www.cnblogs.com/luxd/p/11933686.html
Copyright © 2020-2023  润新知