• Arrays.asList 为什么不能 add 或者 remove 而 ArrayList 可以


    分析如下例子:

     1 import java.util.Arrays;
     2 import java.util.List;
     3 
     4 
     5 public class Test {
     6     public static void main(String[] args) {
     7         Integer[] a = {0,1,2,3,4,5,6};
     8         List<Integer> c = Arrays.asList(a);
     9         for (Integer integer : c) {
    10             System.out.println(integer);
    11         }
    12         c.add(7);
    13         c.remove(0);
    14         
    15     }
    16 }

    打印结果为:

    0
    1
    2
    3
    4
    5
    6
    Exception in thread "main" java.lang.UnsupportedOperationException
    	at java.util.AbstractList.add(AbstractList.java:151)
    	at java.util.AbstractList.add(AbstractList.java:89)
    	at com.cys.collections.MapTest.main(MapTest.java:14)
    

    查看Arrays.asList() 底层实现:

       public static <T> List<T> asList(T... a) {
    	return new ArrayList<T>(a);
        }
    

    实现同样是ArrayList ! But,再向下看:

    文件名: Arrays$ArrayList.class 表明ArrayList是一个Arrays 类的内部类,与我们平时使用的ArrayList 并不同;

    它继承了一个抽象类AbstractList并使用该抽象类的add 和 remove方法:

     public boolean add(E o) {
    	add(size(), o);
    	return true;
        }
    
    public void add(int index, E element) {
    	throw new UnsupportedOperationException();
        }
     public E remove(int index) {
    	throw new UnsupportedOperationException();
        }
    

      全部抛出了一个UnsupportedOperationException 异常,说明该list不支持改变它长度的情况。

         但是同样是数组实现的直接  new 的 ArrayList为什么就可以呢?

      让我们看一看它的add 代码:

        

     1  public boolean add(E o) {
     2     ensureCapacity(size + 1);  // Increments modCount!!
     3     elementData[size++] = o;
     4     return true;
     5     }
    
      public boolean addAll(Collection<? extends E> c) {
    	Object[] a = c.toArray();
            int numNew = a.length;
    	ensureCapacity(size + numNew);  // Increments modCount
            System.arraycopy(a, 0, elementData, size, numNew);
            size += numNew;
    	return numNew != 0;
        }
    

      

    这两个方法里面的第一行,均是确信当前容量是否能容下新增加的对象。

    public void ensureCapacity(int minCapacity) {
    	modCount++;
    	int oldCapacity = elementData.length;
    	if (minCapacity > oldCapacity) {
    	    Object oldData[] = elementData;
    	    int newCapacity = (oldCapacity * 3)/2 + 1;
        	    if (newCapacity < minCapacity)
    		newCapacity = minCapacity;
    	    elementData = (E[])new Object[newCapacity];
    	    System.arraycopy(oldData, 0, elementData, 0, size);
    	}
        }
    

      此方法里,一旦发现容量不足,会自动扩充容量,新的大小是

         int newCapacity = (oldCapacity * 3)/2 + 1

         再通过拷贝方法,新new一个数组。

      remove 就很简单了,就是单纯的删去一个位置上的数据,然后把后面的数据依次向前挪。

         所以 new ArrayList 可以 remove 和add 。

        题外话:

        我们看到ArrayList 的扩充是原来的1.5倍+1,所以为了避免频繁扩充带来的扩充损耗,应当尽可能大的new ArrayList的初始长度,

    但是太大的话,如果数据增长很慢,就会占用很多没用的内存,所以这个长度还是需要根据业务的实际情况,合理申请。

          http://www.cnblogs.com/caoyusongnet/

  • 相关阅读:
    团队-科学计算器-设计文档
    团队-科学计算器-开发环境搭建过程
    《个人-GIT使用方法》
    结对-结对编项目作业名称-开发环境搭建过程
    结对编程项目作业-结对编项目设计文档
    阅读笔记,构建之法
    课程总结
    -阅读提问-3
    构建之法:现代软件工程-阅读笔记
    《科学计算机——环境搭建》
  • 原文地址:https://www.cnblogs.com/caoyusongnet/p/5541772.html
Copyright © 2020-2023  润新知