谈Java List 拷贝

    Java开发人员在开发过程中经常遇到需要对List进行复制的场景,在这些场景中又经常因为没注意浅拷贝和深拷贝的区别而出现异常,下面我们花一点时间,来谈谈Java List的拷贝问题。已经有很多文章列出浅拷贝和深拷贝的各种方式,我们针对使用场景,看看这些拷贝方法。  
    1. List的元素个数不变(而非元素内容不变)
    这种场景主要是当不希望对进行增加/减少元素(不涉及修改已有元素的内容),但不希望影响原始List。
    先定义一个User类供使用
    public class User {
        private String name;
        private int age;
        User(){}
        User(String name, int age){
        this.name = name;
        this.age = age;
        }
    } 
     a) addAll
        List<User> list1= new ArrayList<>();
        User user1 = new User("alice", 20);
        User user2 = new User("bob", 30);
        list1.add(user1);
        list1.add(user2);
        List<User> list2 = new ArrayList<>();
        list2.addAll(list1);
        
        [1] 删除
        list2.remove(0); 
        打印:
        System.out.println(JSON.toJSONString(list1));
        System.out.println(JSON.toJSONString(list2)); 
        输出结果:
        list1 = [{"age":20,"name":"alice"},{"age":30,"name":"bob"}]
        list2 = [{"age":30,"name":"bob"}]
        
        [2] 增加
        然后将删除语句改为如增加语句:
        User user3 = new User("Jessica", 25);
        list2.add(user3);
        输出结果: 
        list1 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"},{"age":25,"name":"Jessica"}]
        可以看到,新List的元素增改没有影响老List。
        [3] 修改元素
        接下来看下元素内容的修改是影响原始List
        list2.get(0).setAge(999);
        打印:
        System.out.println(JSON.toJSONString(list1));
        System.out.println(JSON.toJSONString(list2)); 
        输出结果: 
        list1 = [{"age":999,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":999,"name":"Alice"},{"age":30,"name":"Bob"}]
        我们看到修改其实是对原始List的修改,这点也容易理解,List是new的,所以List的相关不受影响,但元素并不是new的,所以修改的其实是原来的元素。        
    b) 不重新new元素的 循环遍历复制        
        for(User user:list1){
            list2.add(user);
        }
        [1] 删除
        list2.remove(0); 
        输出结果:
        list1 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":30,"name":"Bob"}]    
        [2] 增加
        然后将删除语句改为如增加语句:
        list2.add(new User("Jessica", 25));
        输出结果: 
        list1 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"},{"age":25,"name":"Jessica"}]
        可以看到,新List的元素增改没有影响老List。
        [3] 修改元素
        接下来看下元素内容的修改是影响原始List
        list2.get(0).setAge(999);
        输出结果: 
        list1 = [{"age":999,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":999,"name":"Alice"},{"age":30,"name":"Bob"}]
        我们看到不重新new元素的循环遍历,效果和addAll是一样的。
    c) 重新new元素的 循环遍历复制   
        for(User user:list1){
            User newUser = new User();
            newUser.setAge(user.getAge());
            newUser.setName(user.getName());
            list2.add(newUser);
        }
      [3] 修改元素
        接下来看下元素内容的修改是影响原始List
        list2.get(0).setAge(999);
        输出结果: 
        list1 = [{"age":20,"name":"Alice"},{"age":30,"name":"Bob"}]
        list2 = [{"age":999,"name":"Alice"},{"age":30,"name":"Bob"}]
        不影响原始List,这个可以想到的,List和元素都是new的,当然不影响。     

        


    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值