ArrayList

ArrayList


源码解析转载自(已经很详细): http://blog.csdn.net/u010887744/article/details/49496093

ArrayList常见的面试题转载自: https://www.cnblogs.com/softidea/p/6410680.html

总结:
ArrayList是基于动态数组进行实现的。适合做查询,因为存在下标,不适合做增加和删除,因为会进行数组的复制,然后调用System.arrayCopy( )方法,特别消耗资源。
因此:对数据做查询操作多于增加和删除操作时,ArrayList比较适合。

question1:是如何基于动态数组的?
        ArrayList的add操作首先会对数组进行检查,判断数组中的数+1是否大于其默认值10,若不大于则不进行扩容操作,若大于10,则会进行+1的扩容操作,然后底层调用System.arrayCopy( )将原数据复制到新数据进行扩容。
remove操作会将数据中的-1,容量大于10,会进行缩容操作,调用trimToSize( )恢复到10,容易=10,不会进行此操作。
注:System.arrayCopy( )会特别的消耗资源,因此ArrayList不适合做增加和删除操作。

question2:ArrayList的扩容机制?
ArrayList list = new ArrayList( );
这样子创建集合的时候,创建的容量默认是0。jdk1.8中在对集合首次进行add的时候,会将默认的容量赋值给集合的size。
扩容机制:当集合add元素的时候,会对内部的数组的size进行检查,若>10会进行扩容,扩容的源码:
        private void grow(int minCapacity) {
            int oldCapacity = elementData.length;
            // 此处为扩容:集合原先的容量 + 原先容量的右移1位。
            int newCapacity = oldCapacity + (oldCapacity >> 1);
            if (newCapacity - minCapacity < 0)
                newCapacity = minCapacity;
            if (newCapacity - MAX_ARRAY_SIZE > 0)
                newCapacity = hugeCapacity(minCapacity);
            // minCapacity is usually close to size, so this is a win:
            elementData = Arrays.copyOf(elementData, newCapacity);
        }

注:右移位操作,若原先为10(十进制表示为1*2^1=2),则右移变成01(十进制表示为1*2^0=1),即右移一位表示/2。计算机是对二进制进行计算的。

因此:grow方法中机制为:扩容后size = 扩容前size + 扩容前size/2 = 1.5扩容前size。

ArrayList内部扩容机制举例说明:
如果我们现在连续插入17的对象,就会扩容两次,第一次是在插入第11个对象时(扩容为size = 10*1.5 = 15),第二次是在插入第16个对象时扩容(扩容为size= 15*1.5+1 = 22.5)。

本篇博客,穿插Vector实现类。
Vector与ArrayList比较:
1:Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的同步必然要影响性能,因此,ArrayList的性能比Vector好。 
2:当Vector或ArrayList中的元素超过它的初始大小时,Vector会将它的容量翻倍(2倍),而ArrayList只增加50%(1.5倍)的大小,这样ArrayList就有利于节约内存空间。

注:ArrayList内部扩容源码:
int newCapacity = oldCapacity + (oldCapacity >> 1);---扩容1.5倍。

Vector内部扩容源码:
int newCapacity = oldCapacity + ((capacityIncrement > 0) ?capacityIncrement : oldCapacity);----capacityIncrement :增长系数,当增长的时候,capacityIncrement为0,扩容2倍 


注:Vector现在一般都不使用,因为其内部的方法都是synchronized修饰的同步方法,会造成多线程的阻塞问题,影响性能。若集合(CopyOnWriteArrayList和ArrayList)是在方法内部创建,则用ArrayList,因为多线程不会对局部变量中的数据造成影响;若集合是当做成员变量进行使用的,存在多线程的情况下可以用jdk1.5中java.concurrent包中的CopyOnWriteArrayList并发集合类进行处理。因此,综上所述,Vector不适用。

猜你喜欢

转载自834434471.iteye.com/blog/2412913