1 场景
有一个公用的Map<String, UserEntity> map,多个方法会使用map,对他的操作如下:
(1)方法A将依据uid提取实体,转为List userEntityList;
(2)遍历userEntityList并修改实体的属性;
(3)方法B读取map数据;
- 问题:
方法B读取的map数据已经是方法A修改过的数据,不是原始map值 - 原因:
使用stream遍历map时,使用了引用传递,即将Map中的对象直接赋值给userEntityList,而不是新建对象赋值给userEntityList,
发生了引用传递,浅拷贝。 - 方案:
遍历map时,新建对象,保证是“值”传递,深拷贝。
友情链接
Java基础系列:引用传递与值传递
Java基础系列:浅克隆和深克隆
2 Test
2.1 实体
测试使用的类。
package common.entity;
/**
* User实体
*
* @author xindaqi
* @since 2021-01-23
*/
public class UserEntity {
/**
* 用户id
*/
private String uid;
/**
* 用户名称
*/
private String nickname;
/**
* 用户性别
*/
private String sex;
public UserEntity() {
}
public UserEntity(String uid, String nickname, String sex) {
this.uid = uid;
this.nickname = nickname;
this.sex = sex;
}
public UserEntity copy() {
return new UserEntity(uid, nickname, sex);
}
public String getUid() {
return uid;
}
public void setUid(String uid) {
this.uid = uid;
}
public String getNickname() {
return nickname;
}
public void setNickname(String nickname) {
this.nickname = nickname;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
@Override
public String toString() {
return "UserEntity{" +
"uid=" + uid +
", nickname='" + nickname + '\'' +
", sex='" + sex + '\'' +
'}';
}
}
2.2 引用传递
2.2.1 Test
package lambda_expression;
import common.entity.UserEntity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Lambda测试引用传递.
*
* @author xindaqi
* @date 2021-06-25 16:56
*/
public class LambdaDataTransmitTest {
private static final Logger logger = Logger.getLogger("LambdaDataTransmitTest");
/**
* 赋值时使用源对象,此时为引用传递,
* 即修改结果对象时,源对象同步修改
*
* @param userEntityList 结果对象
* @param uidList uid列表
* @param userEntityMap 源对象
*/
public static void referenceTest(List<UserEntity> userEntityList, List<String> uidList, Map<String, UserEntity> userEntityMap) {
userEntityList = uidList.stream().filter(uid -> null != userEntityMap.get(uid)).map(uid -> userEntityMap.get(uid)).collect(Collectors.toList());
userEntityList.stream().forEach(s -> s.setNickname("foreach"));
logger.info("userEntity list changed:" + userEntityList);
logger.info("map changed: " + userEntityMap);
}
public static void main(String[] args) {
List<UserEntity> userEntityList = new ArrayList<>();
UserEntity u1 = new UserEntity("u1", "111", "male");
UserEntity u2 = new UserEntity("u2", "222", "female");
UserEntity u3 = new UserEntity("u3", "333", "male");
Map<String, UserEntity> map = new HashMap<>();
map.put("u1", u1);
map.put("u2", u2);
map.put("u3", u3);
logger.info("map original : " + map);
List<String> uidList = Stream.of("u1", "u2").collect(Collectors.toList());
/**
* 测试时一个一个测
*/
LambdaDataTransmitTest.referenceTest(userEntityList, uidList, map);
}
}
2.2.2 结果
六月 25, 2021 6:39:12 下午 lambda_expression.LambdaDataTransmitTest main
信息: map original : {u1=UserEntity{uid=u1, nickname='111', sex='male'}, u2=UserEntity{uid=u2, nickname='222', sex='female'}, u3=UserEntity{uid=u3, nickname='333', sex='male'}}
六月 25, 2021 6:39:12 下午 lambda_expression.LambdaDataTransmitTest referenceTest
信息: userEntity list changed:[UserEntity{uid=u1, nickname='foreach', sex='male'}, UserEntity{uid=u2, nickname='foreach', sex='female'}]
六月 25, 2021 6:39:12 下午 lambda_expression.LambdaDataTransmitTest referenceTest
信息: map changed: {u1=UserEntity{uid=u1, nickname='foreach', sex='male'}, u2=UserEntity{uid=u2, nickname='foreach', sex='female'}, u3=UserEntity{uid=u3, nickname='333', sex='male'}}
2.3 值传递
2.3.1 Test
package lambda_expression;
import common.entity.UserEntity;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
import java.util.stream.Collectors;
import java.util.stream.Stream;
/**
* Lambda测试引用传递.
*
* @author xindaqi
* @date 2021-06-25 16:56
*/
public class LambdaDataTransmitTest {
private static final Logger logger = Logger.getLogger("LambdaDataTransmitTest");
/**
* 赋值时新建对象,保证是值传递,
* 即修改结果对象时,不影响源对象
*
* @param userEntityList 结果对象
* @param uidList uid列表
* @param userEntityMap 源对象
*/
public static void valueTest(List<UserEntity> userEntityList, List<String> uidList, Map<String, UserEntity> userEntityMap) {
userEntityList = uidList.stream().filter(uid -> null != userEntityMap.get(uid)).map(uid -> new UserEntity(userEntityMap.get(uid).getUid(), userEntityMap.get(uid).getNickname(), userEntityMap.get(uid).getSex())).collect(Collectors.toList());
userEntityList.stream().forEach(s -> s.setNickname("foreach"));
logger.info("userEntity list changed:" + userEntityList);
logger.info("map changed: " + userEntityMap);
}
/**
* 赋值时新建对象,保证是值传递,
* 即修改结果对象时,不影响源对象
*
* @param userEntityList 结果对象
* @param uidList uid列表
* @param userEntityMap 源对象
*/
public static void valueCopyTest(List<UserEntity> userEntityList, List<String> uidList, Map<String, UserEntity> userEntityMap) {
userEntityList = uidList.stream().filter(uid -> null != userEntityMap.get(uid)).map(uid -> {
UserEntity userEntity = userEntityMap.get(uid);
return userEntity.copy();
}).collect(Collectors.toList());
userEntityList.stream().forEach(s -> s.setNickname("foreach"));
logger.info("userEntity list changed:" + userEntityList);
logger.info("map changed: " + userEntityMap);
}
public static void main(String[] args) {
List<UserEntity> userEntityList = new ArrayList<>();
UserEntity u1 = new UserEntity("u1", "111", "male");
UserEntity u2 = new UserEntity("u2", "222", "female");
UserEntity u3 = new UserEntity("u3", "333", "male");
Map<String, UserEntity> map = new HashMap<>();
map.put("u1", u1);
map.put("u2", u2);
map.put("u3", u3);
logger.info("map original : " + map);
List<String> uidList = Stream.of("u1", "u2").collect(Collectors.toList());
/**
* 测试时一个一个测
*/
LambdaDataTransmitTest.valueTest(userEntityList, uidList, map);
// LambdaDataTransmitTest.valueCopyTest(userEntityList, uidList, map);
}
}
2.3.2 结果
六月 25, 2021 6:42:16 下午 lambda_expression.LambdaDataTransmitTest main
信息: map original : {u1=UserEntity{uid=u1, nickname='111', sex='male'}, u2=UserEntity{uid=u2, nickname='222', sex='female'}, u3=UserEntity{uid=u3, nickname='333', sex='male'}}
六月 25, 2021 6:42:16 下午 lambda_expression.LambdaDataTransmitTest valueTest
信息: userEntity list changed:[UserEntity{uid=u1, nickname='foreach', sex='male'}, UserEntity{uid=u2, nickname='foreach', sex='female'}]
六月 25, 2021 6:42:16 下午 lambda_expression.LambdaDataTransmitTest valueTest
信息: map changed: {u1=UserEntity{uid=u1, nickname='111', sex='male'}, u2=UserEntity{uid=u2, nickname='222', sex='female'}, u3=UserEntity{uid=u3, nickname='333', sex='male'}}