Java中实现引用类型集合的深,浅拷贝(for循环遍历+BeanUtils)

1、场景:

现有一个ShoppingAddDto类和一个ShoppingItemProperty类,ShoppingAddDto类中包含以ShoppingItemProperty为属性的字段。现有多个ShoppingAddDto类的对象组成一个List集合名为List,实现此List集合的拷贝生成ListNew,使得拷贝后的ListNew集合修改结果不影响之前的List集合。

== 注==:
这里类的嵌套为引用类型,下面会分别演示引用类型的深浅拷贝(即一层和多层的拷贝),如大家有简便的方式,欢迎留言讨论。

== 拓展:==
对List集合进行按指定条件进行分组形成Map的形式

2、解决方法:

对List集合进行for循环遍历,每次循环用BeanUtils.copyProperties(Object source, Object target)方法进行对象的拷贝,

3、代码实现:


import org.springframework.beans.BeanUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

public class test007 {

    static class ShoppingItemProperty{
        /**
         * 属性名称
         */
        private String name;

        /**
         * 属性值
         */
        private String value;

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getValue() {
            return value;
        }

        public void setValue(String value) {
            this.value = value;
        }

        @Override
        public String toString() {
            return "ShoppingItemProperty{" +
                    "name='" + name + '\'' +
                    ", value='" + value + '\'' +
                    '}';
        }
    }

    static class ShoppingAddDto{
        private String key;
        private List<ShoppingItemProperty> shoppingItemProperty;

        public String getKey() {
            return key;
        }

        public void setKey(String key) {
            this.key = key;
        }

        public List<ShoppingItemProperty> getShoppingItemProperty() {
            return shoppingItemProperty;
        }

        public void setShoppingItemProperty(List<ShoppingItemProperty> shoppingItemProperty) {
            this.shoppingItemProperty = shoppingItemProperty;
        }

        @Override
        public String toString() {
            return "ShoppingAddDto{" +
                    "key='" + key + '\'' +
                    ", shoppingItemProperty=" + shoppingItemProperty +
                    '}';
        }

        public String getPropertyValueByName(String name) {
            String result = null;
            if(shoppingItemProperty != null && !shoppingItemProperty.isEmpty()) {
                for (ShoppingItemProperty property : shoppingItemProperty) {
                    if(name.equals(property.getName())) {
                        result = property.getValue();
                        break;
                    }
                }
            }
            return result;
        }

    }

    public static void main(String[] args) {

        List<ShoppingAddDto> shoppingAddDtoList = new ArrayList<>();

        List<ShoppingItemProperty> kvs1 = new ArrayList<>();
        ShoppingItemProperty kv1 = new ShoppingItemProperty();
        kv1.setName("disksSize");
        kv1.setValue("1");
        kvs1.add(kv1);
        ShoppingItemProperty kv2 = new ShoppingItemProperty();
        kv2.setName("joker2");
        kv2.setValue("2");
        kvs1.add(kv2);
        ShoppingAddDto shoppingAddDto = new ShoppingAddDto();
        shoppingAddDto.setKey("addDto1");
        shoppingAddDto.setShoppingItemProperty(kvs1);
        shoppingAddDtoList.add(shoppingAddDto);

        List<ShoppingItemProperty> kvs2 = new ArrayList<>();
        ShoppingItemProperty kv3 = new ShoppingItemProperty();
        kv3.setName("disksSize");
        kv3.setValue("2");
        kvs2.add(kv3);
        ShoppingItemProperty kv4 = new ShoppingItemProperty();
        kv4.setName("joker2");
        kv4.setValue("2");
        kvs2.add(kv4);
        ShoppingAddDto shoppingAddDto2 = new ShoppingAddDto();
        shoppingAddDto2.setKey("addDto2");
        shoppingAddDto2.setShoppingItemProperty(kvs2);
        shoppingAddDtoList.add(shoppingAddDto2);

        List<ShoppingItemProperty> kvs3 = new ArrayList<>();
        ShoppingItemProperty kv5 = new ShoppingItemProperty();
        kv5.setName("disksSize");
        kv5.setValue("1");
        kvs3.add(kv5);
        ShoppingItemProperty kv6 = new ShoppingItemProperty();
        kv6.setName("joker2");
        kv6.setValue("2");
        kvs3.add(kv6);
        ShoppingAddDto shoppingAddDto3 = new ShoppingAddDto();
        shoppingAddDto3.setKey("addDto3");
        shoppingAddDto3.setShoppingItemProperty(kvs3);
        shoppingAddDtoList.add(shoppingAddDto3);

        // 浅拷贝:
        List<ShoppingAddDto> addDtosNewList = new ArrayList<>();
        for (ShoppingAddDto addDto : shoppingAddDtoList){
            ShoppingAddDto addDtoNew = new ShoppingAddDto();
            BeanUtils.copyProperties(addDto,addDtoNew);
            addDtosNewList.add(addDtoNew);
        }
        // 浅拷贝
        // 修改新list的key值,之前的list不受影响。
        // 但是修改引用属性shoppingItemProperty,会都受影响。
        System.out.println("修改addDtosNewList前的shoppingAddDtoList:" + shoppingAddDtoList);
        System.out.println("修改addDtosNewList前的addDtosNewList:    " + addDtosNewList);
        addDtosNewList.get(0).setKey("100");
        System.out.println("修改addDtosNewList后的addDtosNewList:    " + addDtosNewList);
        System.out.println("修改addDtosNewList后的shoppingAddDtoList:" + shoppingAddDtoList);
//        addDtosNewList.get(0).getShoppingItemProperty().get(0).setValue("100");
//        System.out.println("修改addDtosNewList后的addDtosNewList:    " + addDtosNewList);
//        System.out.println("修改addDtosNewList后的shoppingAddDtoList:" + shoppingAddDtoList);
        System.out.println("=================================================");
        System.out.println("深拷贝:");

        // 深拷贝:
        List<ShoppingAddDto> addDtosDeepCopyList = new ArrayList<>();
        for (ShoppingAddDto addDto : shoppingAddDtoList){
            ShoppingAddDto addDtoNew = new ShoppingAddDto();
            List<ShoppingItemProperty> propertiesNew = new ArrayList<>();
            for (ShoppingItemProperty shoppingItemProperty : addDto.getShoppingItemProperty()){
                ShoppingItemProperty propertyNew = new ShoppingItemProperty();
                BeanUtils.copyProperties(shoppingItemProperty,propertyNew);
                propertiesNew.add(propertyNew);
            }
            BeanUtils.copyProperties(addDto,addDtoNew);
            addDtoNew.setShoppingItemProperty(propertiesNew);
            addDtosDeepCopyList.add(addDtoNew);
        }
        System.out.println("修改addDtosDeepCopyList前的shoppingAddDtoList:" + shoppingAddDtoList);
        System.out.println("修改addDtosDeepCopyList前的addDtosNewList:    " + addDtosDeepCopyList);
        addDtosDeepCopyList.get(0).getShoppingItemProperty().get(0).setValue("100");
        System.out.println("修改addDtosDeepCopyList后的addDtosDeepCopyList:" + addDtosDeepCopyList);
        System.out.println("修改addDtosDeepCopyList后的shoppingAddDtoList:" + shoppingAddDtoList);

        // 拓展:将List集合中disksSize字段值一样的进行分组,组成Map的结构形式。
        Map<String, List<ShoppingAddDto>> listMap = shoppingAddDtoList.stream().collect(Collectors.groupingBy(t -> t.getPropertyValueByName("disksSize")));
        System.out.println(listMap);


    }
}

运行结果展示:
运行结果
具体执行结果如下:

修改addDtosNewList前的shoppingAddDtoList:[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosNewList前的addDtosNewList:    [ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosNewList后的addDtosNewList:    [ShoppingAddDto{key='100', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosNewList后的shoppingAddDtoList:[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
=================================================
深拷贝:
修改addDtosDeepCopyList前的shoppingAddDtoList:[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosDeepCopyList前的addDtosNewList:    [ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosDeepCopyList后的addDtosDeepCopyList:[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='100'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
修改addDtosDeepCopyList后的shoppingAddDtoList:[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}]
{1=[ShoppingAddDto{key='addDto1', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}, ShoppingAddDto{key='addDto3', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='1'}, ShoppingItemProperty{name='joker2', value='2'}]}], 2=[ShoppingAddDto{key='addDto2', shoppingItemProperty=[ShoppingItemProperty{name='disksSize', value='2'}, ShoppingItemProperty{name='joker2', value='2'}]}]}

4、总结

浅拷贝就是利用for循环 + BeanUtils的copyProperties方法实现。
深拷贝就是再其那套一层循环,将更深层次的引用类型属性逐一通过BeanUtils的copyProperties的方法进行拷贝。

没有for循环解决不了的问题,如果有那就两个
这种方式确实有点low,希望大家提出更优解讨论。

5、其余方式实现深浅拷贝

1、转载:
https://www.cnblogs.com/lzzRye/p/9459465.html

  • 6
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值