今天同事问我怎样将一个列表(list1)拷贝到另外一个列表(list2),而后修改新的列表(list2)不会影响到旧的列表(list1),想了一想,这是深拷贝啊。java
但是,除了循环new还有别的办法吗,想了又想,本身也是啥都不懂啊,赶忙百度学习一下,因而就找到了java.util.Collections.copy(),一开始还觉得这个是个深拷贝呢,没想到仍是个浅拷贝。虽然还没找到深拷贝的方法去解决同事的问题,但仍是要学习一下这个浅拷贝,毕竟也是有用滴。数组
先写个单元测试试一下:dom
@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()等相关操做时,实际元素个数才会发生改变。spa
好吧,元凶找到了。只要给descList塞一些空对象就完事了。code
@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。blog
@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); } }
嘻嘻,就这些了,接着找找深拷贝的知识吧,顺便还要总结下浅拷贝和深拷贝的知识呢。
"愿你既能够安于朝九晚五,波澜不惊;又能随时出发,踏浪远航。"