我是靠谱客的博主 勤奋日记本,最近开发中收集的这篇文章主要介绍Java list 使用的过程中出现的问题list的使用-----深拷贝,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

list的使用-----深拷贝

1、问题

一次开发中,使用list的时候,对list的内容进行改变时,出现数据丢失的问题,最后排查数据找到问题的原因,是因为使用list的是浅拷贝,值引用。

2、产生的原因

List<Question> questionList = new ArrayList<>();
Question question1 = new Question();
question1.setQuestionBody("111111111");
questionList.add(question1);
List<Question> questionList= questionList.stream().filter(item -> item.getId().equals(0)).collect(Collectors.toList());

System.arraycopy

使用 arrayList.addAll(); 进行数组的生成,结果还是浅拷贝,因为其使用的是System.arraycopy
源码如下:

    public boolean addAll(Collection<? extends E> c) {
        Object[] a = c.toArray();
        int numNew = a.length;
        ensureCapacityInternal(size + numNew);  // Increments modCount
        System.arraycopy(a, 0, elementData, size, numNew);
        size += numNew;
        return numNew != 0;
    }

System.arraycopy 就是将新的数组指向的原数组的内存地址
在这里插入图片描述
所以是无法实现深拷别,还是浅拷贝,别被别人忽悠。

Arrays.copyOf

源码


 public static <T> T[] copyOf(T[] original, int newLength) {
        return (T[]) copyOf(original, newLength, original.getClass());
    }

 public static <T,U> T[] copyOf(U[] original, int newLength, Class<? extends T[]> newType) {
        @SuppressWarnings("unchecked")
        T[] copy = ((Object)newType == (Object)Object[].class)
            ? (T[]) new Object[newLength]
            : (T[]) Array.newInstance(newType.getComponentType(), newLength);
        System.arraycopy(original, 0, copy, 0,
                         Math.min(original.length, newLength));
        return copy;
    }

查看其源码还是如此的使用的是 System.arraycopy,终究还是浅拷贝。

3、解决

		List<Question> newQuestionList = new ArrayList<>();
        int index = 0;
        for (Question question: questionList) {
            Question question5= new Question();
            BeanUtils.copyProperties(question,question5);
            question5.setId(index);
            question5.setQuestionBody(index + "");
            newQuestionList.add(question5);
            index++;
        }

即就是需要重新new一个对象,分配一块新的内存地址,这样新的数组和原来的之间就没有关系,改变新的数组并不会影响原来的数组的内容。

结果
在这里插入图片描述
又或者

List<Question> list = questionList.stream().filter(doc -> 	doc.getQuestionBody().equals("111111111")).map(item -> {
            Question question = new Question();
            BeanUtils.copyProperties(item, question);
            return question;
        }).collect(Collectors.toList());

所以使用map去创建一个对象,然后进行收集,生成一个全新的对象,则两个对象之间是没有任何的关系。

结果
在这里插入图片描述

4、总结

使用list stream,对原始list修改其中的某些值时,最好生成一个新的list这样就不会造成原数组的值发生改变影响自己的后续处理,因为自己操作的是同一块内存区域。
因此,如果原始数组只是用一次,可以不进行map收集,这样可减少内存的开销、

最后

以上就是勤奋日记本为你收集整理的Java list 使用的过程中出现的问题list的使用-----深拷贝的全部内容,希望文章能够帮你解决Java list 使用的过程中出现的问题list的使用-----深拷贝所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(55)

评论列表共有 0 条评论

立即
投稿
返回
顶部