ArrayList和LinkerList区别和ArrayList简单解析

ArrayList和LinkerList区别和ArrayList简单解析,第1张

ArrayList和LinkerList区别和ArrayList简单解析 1,数组和集得区别?
(1)创建数组要初始化长度,且长度不可改变
     集合长度可变
(2)数组数据类型可以是基本数据类型,也可以是引用数据类型
     集合只能是引用数据类型
2,list和set的区别?
(1)list能保证插入数据顺序排序,数据可重复
     set不保证插入数据顺序排序,数据不可重复
(2)list可以通过索引获取数据,set不能通过索引获取数据
3,list主要实现类:arraylist,linkedlist,vectory
(1)ArrayList:
     底层是Object类型的动态数组在内存中需要一片连续得空间,线程不安全(线程安全就是多线程访问时,采用了加锁机制),效率高,数据可重复,可以为null
     查询快:因为是数组具有下标索引
     增删慢:添加和删除要移动下标位置之后的索引,如果元素插在数组末尾也很快,需要扩容时都慢
     空间:需要连续空间,并且扩容是1.5倍有可能一篇空间没用到
(2)linkedList:
     底层是双向链表(双向链表有俩个指针分别指向节点前后,第一个节点指向前为null,最后一个节点指向后为null)不需要连续空间,线程不安全,效率高,可以存储重复元素,没有长度的概念,不存在扩容问题,
     查询慢:没有索引,迭代链表查询,但是采用了二分折半查询。只需要遍历一半链表,但还是慢
     增删快:只需要移动指针,默认添加到尾部
     空间:每个节点都要存储指向前一个和后一个节点的指针
(3)Vectory:底层数据结构是数组,查询快,增删慢,线程安全,效率低,可以存储重复元素
ArrayList源码解析add:jdk1.8
(1)创建指定大小容量得集合,如果是0则创建一个object类型得空数组,否则参数不合法
ArrayList代码中得3种构造方法:
    public ArrayList(int initialCapacity) {
        if (initialCapacity > 0) {
            this.elementData = new Object[initialCapacity];
        } else if (initialCapacity == 0) {
        this.elementData = EMPTY_ELEMENTDATA;
        } else {
            throw new IllegalArgumentException("Illegal Capacity: "+initialCapacity);
        }
    }
(2)创建一个object类型得空数组
public ArrayList() {
    this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
}
(3)add:默认添加到尾部,所以很快,
        带有索引的插入,先判断所引是否越界,无论是否扩容都要拷贝数组,在拷贝数组时会对索引进行+1
        数组拷贝方法:System.arraycopy(),返回的是新对象
        remove也一样,nt numMoved = size - index - 1; System.arraycopy()移动索引,复制数组
    
    public boolean add(E e) {
        //判断数组是否需要初始化和数组是否需要扩容,同时size数组长度进行了+1
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        //将元素插在索引的最后一位+1,所以保证了arraylist中元素插入有序
        elementData[size++] = e;
        return true;
    }
    
    private void ensureCapacityInternal(int minCapacity) {
        //elementData是存放元素的对象数组
        //如果数组是空的,就初始化长度为10
        if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        //minCapacity=初始化长度19,或者数组中的元素长度+1
        ensureExplicitCapacity(minCapacity);
   }
   
   private void ensureExplicitCapacity(int minCapacity) {
    modCount++;

    //数组的元素长度+1,大于原数组长度 ,就需要进行扩容
    if (minCapacity - elementData.length > 0)
        grow(minCapacity);
   }
    //开始扩容
    private void grow(int minCapacity) {
    // overflow-conscious code
    int oldCapacity = elementData.length;
    //扩容后=扩容前+(扩容前/2,扩容1.5倍(位移一位除以2)
    int newCapacity = oldCapacity + (oldCapacity >> 1);
    //若果扩容后的长度 - 数组中元素长度+1 小于0,则数组长度为原始数组长度+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:
    //创建新长度newCapacity的数组,进行拷贝扩容
    elementData = Arrays.copyOf(elementData, newCapacity);
    }
    
    总结add:
          1,ArrayList添加元素,判断数组是否为空,
             如果为空初始化数组长度为10,
             如果数组不为空,数组中元素长度为原数组中元素长度+1
          2,变化后的数组元素长度减去原数组长度大于0,进行扩容
          3,开始扩容:扩容规则:扩容后=扩容前+(扩容前>>2,扩容1.5倍(位移一位除以2)
          4, 扩容后的长度和变化后的数组长度,谁大谁就是最终的数组长度
          5,扩容:创建新长度的数组,拷贝原数组内容
    问题:ArrayList插入数据如何保证有序的?
            添加元素将元素插在索引的最后一位+1,所以保证了arraylist中元素插入有序,即使是带索引参数插入,也会移动索引排序
          ArrayList如何扩容?
          1,如果数组中元素长度+1大于了数组长度,就需要扩容
          2,扩容规则扩容规则:扩容后=扩容前+(扩容前>>2
          3,扩容规则后的长度如果小于数组元素长度+1,则扩容为原数组元素长度+1
          4,扩容相当于自己拷贝自己,实现扩容
          ArrayList增删查效率?
          1,查询:直接根据索引查询,快
          2,增加:不带参数的增加,默认增加到尾部,快,但是需要扩容时。慢
          3,带索引的增加和删除,拷贝数组时需要移动索引后下标,慢,当需要扩容时更慢
          ArratList为啥线程不安全?如何解决
          当俩个线程同时添加数据的时候,elementData=0的数据有可能会被覆盖
          使用synchronized关键字,Collections.synchronizedList()同步就会有锁机制,效率低

欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/zaji/5683093.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存