List的深拷贝与浅拷贝

0.jpg

Java的浅拷贝(Shallow Copy)、深拷贝(Deep Copy)。

浅拷贝(Shallow Copy)

1、对于数据类型是基本数据类型的成员变量,浅拷贝会直接进行值传递,也就是将该属性值复制一份给新的对象。因为是两份不同的数据,所以对其中一个对象的该成员变量值进行修改,不会影响另一个对象拷贝得到的数据。

2、对于数据类型是引用数据类型的成员变量,比如说成员变量是某个数组、某个类的对象等,那么浅拷贝会进行引用传递,也就是只是将该成员变量的引用值(内存地址)复制一份给新的对象。因为实际上两个对象的该成员变量都指向同一个实例。在这种情况下,在一个对象中修改该成员变量会影响到另一个对象的该成员变量值。

深拷贝 (Deep Copy)

相对于浅拷贝而言,对于引用类型的修改,并不会影响到对应的copy对象的值。

最近项目中用到ArrayList,对于ArrayList的怎么实现拷贝,尤其是里边存放复杂对象,该怎么处理?
怎么判断两个集合相等,存放的是稍微复杂的对象,非字符串String? 方法很多,比如:

/**
 * 判断两个集合是否相等
 */
  public static boolean isCagoryEqual(List<Category> src, List<Category> dest) {

        if (src.size() != dest.size()) {
            return false;
        }
        for (Category fo : src) {
          
            if (!dest.contains(fo)) {
                return false;
            }
           
 
        }

        return true;
    }

这样,好像还不够,如何判断里边的对象是否相等呢?
请允许我来一段kotlin代码,为什么重写equals,hashCode?

class  Category() : Serializable {
    var id: String = ""
    var name: String = ""
    var priority: Int = 0
    var restaurantId: String = ""
    var isChecked: MutableList<Int> = ArrayList<Int>()
    private val serialVersionUID = 1L

    override fun equals(other: Any?): Boolean {
        if (other is FoodCategory) {
            val foodCategory = other as FoodCategory
            return this.id.equals(foodCategory.id) && this.name.equals(foodCategory.name)
        }

        return super.equals(other)
    }

    override fun hashCode(): Int {
        var result = id.hashCode()
        result = 31 * result + name.hashCode()
        return result
    }
}

需求是两个list不相等,则要使用原来的数据,显示界面,所以要深拷贝原来的list数据。直接贴代码:

 public static <E> List<E> copy(List<E> src) {
        try {
            ByteArrayOutputStream byteOut = new ByteArrayOutputStream();
            ObjectOutputStream out = new ObjectOutputStream(byteOut);
            out.writeObject(src);

            ByteArrayInputStream byteIn = new ByteArrayInputStream(byteOut.toByteArray());
            ObjectInputStream in = new ObjectInputStream(byteIn);
            @SuppressWarnings("unchecked")
            List<E> dest = (List<E>) in.readObject();
            return dest;
        } catch (Exception e) {
            e.printStackTrace();
            return new ArrayList<E>();
        }
    }

如果新旧list数据不一样,撤销新编辑的数据,怎么处理呢?

                newList.clear()
                for (i in 0 until oldList.size) {
                    val category = Category()
                    category.name = oldList[i].name
                    category.id = oldList[i].id
                    category.restaurantId = oldList[i].restaurantId
                
      				...
				   
                    newList.add(category)
                }

总结:

1、Java对对象和基本的数据类型的处理是不一样的。在Java中用对象的作为入口参数的传递则缺省为”引用传递”,也就是说仅仅传递了对象的一个”引用”。当函数体内部对输入变量改变时,实质上就是在对这个对象的直接操作。 除了在函数传值的时候是”引用传递”,在任何用”=”向对象变量赋值的时候都是”引用传递”。

2、 将对象序列化为字节序列后,默认会将该对象的整个对象图进行序列化,再通过反序列即可完美地实现深拷贝。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值