zoukankan      html  css  js  c++  java
  • java.util.Collections.copy():列表List浅拷贝

    今天同事问我怎样将一个列表(list1)拷贝到另一个列表(list2),然后修改新的列表(list2)不会影响到旧的列表(list1),想了一想,这是深拷贝啊。

    可是,除了循环new还有别的办法吗,想了又想,自己也是啥都不懂啊,赶紧百度学习一下,于是就找到了java.util.Collections.copy(),一开始还以为这个是个深拷贝呢,没想到还是个浅拷贝。虽然还没找到深拷贝的方法去解决同事的问题,但还是要学习一下这个浅拷贝,毕竟也是有用滴。

    先写个单元测试试一下:

    @Test
    public void testCollectionsCopy() {
        List<String> srcList = new ArrayList<>();
        srcList.add("张三");
        srcList.add("李四");
        srcList.add("王五");
    
        List<String> descList = new ArrayList<>(3);
        
        Collections.copy(descList, srcList);
    
        for (String desc : descList) {
            System.out.println(desc);
        }
    } 

    结果报错,悲剧了:java.lang.IndexOutOfBoundsException: Source does not fit in dest。下标越界啊。

    赶紧看看java.util.Collections.copy()的源码压压惊。

    public static <T> void copy(List<? super T> dest, List<? extends T> src) {
            int srcSize = src.size();
            if (srcSize > dest.size())
                throw new IndexOutOfBoundsException("Source does not fit in dest");
    
            if (srcSize < COPY_THRESHOLD ||
                (src instanceof RandomAccess && dest instanceof RandomAccess)) {
                for (int i=0; i<srcSize; i++)
                    dest.set(i, src.get(i));
            } else {
                ListIterator<? super T> di=dest.listIterator();
                ListIterator<? extends T> si=src.listIterator();
                for (int i=0; i<srcSize; i++) {
                    di.next();
                    di.set(si.next());
                }
            }
        } 

    通过看源码,发现这个方法是有目标数组和源数组的元素个数进行比较的操作,如果目标数组的元素个数小于源数组的元素个数,则抛出下标越界的异常。

    可是我已经指定了descList的容量为3了呀!难道这个容量不等于实际元素个数吗?通过打印descList.size()才发现,descList的实际元素个数为0。这样我就知道,指定的descList容量为3,只是指定了descList当前容纳的元素个数为3,即descList的容纳能力(Capacity)为3,并不代表descList中有了三个实际的元素。初始化时实际元素个数(Size)永远为0,只有在进行add()和remove()等相关操作时,实际元素个数才会发生改变。

    好吧,元凶找到了。只要给descList塞一些空对象就完事了。

    @Test
    public void testCollectionsCopy() {
        List<String> srcList = new ArrayList<>();
        srcList.add("张三");
        srcList.add("李四");
        srcList.add("王五");
    
        List<String> descList = new ArrayList<>(3);
        descList.add(null);
        descList.add(null);
        descList.add(null);
        descList.add("赵六");
        System.out.println(descList.size());
    
        Collections.copy(descList, srcList);
    
        for (String desc : descList) {
            desc = desc + "是笨蛋";
            System.out.println(desc);
        }
    }

    这里可以发现,给descList指定容量好像并没有什么用,因为ArrayList是可变动态数组队列(底层实现是Array数组),长度会随着实际元素个数自动增大,那么到底是有什么用呢?(保留疑问,这个要看看Java的集合恶补一下知识啦,或者有没有大佬告诉我一下啊)

    也可以中JDK7中新增加的方法Array.asList()来实现,即数组转List。

    @Test
    public void testCollectionsCopy() {
        List<String> srcList = new ArrayList<>();
        srcList.add("张三");
        srcList.add("李四");
        srcList.add("王五");
    
        List<String> descList = Arrays.asList(new String[srcList.size()]);
        System.out.println(descList.size());
    
        Collections.copy(descList, srcList);
    
        for (String desc : descList) {
            desc = desc + "是笨蛋";
            System.out.println(desc);
        }
    }

    其实也可以用addAll()。

    @Test
    public void testCollectionsCopy() {
        List<String> srcList = new ArrayList<>();
        srcList.add("张三");
        srcList.add("李四");
        srcList.add("王五");
    
        List<String> descList = new ArrayList<>();
        descList.addAll(srcList);
        System.out.println(descList.size());
    
        for (String desc : descList) {
            desc = desc + "是笨蛋";
            System.out.println(desc);
        }
    }

    嘻嘻,就这些了,接着找找深拷贝的知识吧,顺便还要总结下浅拷贝和深拷贝的知识呢。

    "愿你既可以安于朝九晚五,波澜不惊;又能随时出发,踏浪远航。"

  • 相关阅读:
    SVM理论之线性分类
    编写自己的sniffer(二)
    二叉树三种非递归遍历的区别
    SVM理论之最优超平面
    [转载] Linux的capability深入分析
    [转载] ftp的模式ACTIVE&PASSIVE
    Linux下压缩不包含路径信息的压缩包
    [ZzDW] 关于Java对象序列化您不知道的5件事
    [转载] Windows如何在cmd命令行中查看、修改、删除与添加、设置环境变量
    [攻略转载] 在飞机上睡觉的七大攻略
  • 原文地址:https://www.cnblogs.com/yanggb/p/10436165.html
Copyright © 2011-2022 走看看