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