线上问题:深拷贝/浅拷贝/引用传递/值传递

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'}}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

天然玩家

坚持才能做到极致

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值