栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

ArrayList和LinkedList

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

ArrayList和LinkedList

ArrayList

扩容机制:

  • ArrayList()会使用长度为0的数组
  • ArrayList(int initialCapacity)使用指定容量的数组
  • public ArrayList(Collection c)会使用c的大小作为数组容量
  • add(Object o) 首次扩容为10,再次扩容为上次容量的1.5倍
  • addAll(Collection c) 没有元素时,扩容为Math.max(10,实际元素的个数),有元素时Math.max(原容量1.5倍(实际是原容量>>1+原容量),实际元素的个数)

Iterator 的fail-fast

  • ArrayList是fail-fast的典型代表,遍历时不能修改,尽快失败

  • 一旦发现遍历的同时有人来修改,则立即抛异常(下一轮循环时报错—并发修改异常)

​

private static void failFast() {

    ArrayList list = new ArrayList<>();

    list.add("A");
    list.add("B");
    list.add("C");

    for (Object o : list) {
        System.out.println(o);
    }
    System.out.println(list);
}

public static void main(String[] args) {
    failFast();
}
 
  • 增强for循环底层开始先创建一个迭代器()

    • 初始化迭代器的变量,其中的 : int expectedModCount = modCount用来记录集合被修改了多少次

      • modCount:是list集合的变量,记录集合倍修改的次数
      • expectedModCount :迭代器的变量,记录迭代器刚开始迭代时的修改次数
    • 然后调用迭代器hasNext()元素判定有没有下一个元素,next()来移动到下一个元素

      • 在next()方法中都会调用checkForComodification()方法:把迭代器一开始的修改次数跟我们外面list修改次数进行对比。如果相等,什么都不会做,若不相等就抛异常

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();
        }
        

Iterator 的fail-safe

  • CopeOnWriteArrayList是fail-safe的典型代表,遍历时运行修改,原理是读写分离

  • 发现遍历的同时有人来修改,应当能有应对策略,例如牺牲一致性让整个遍历运行完成(就是当前能继续遍历,输出的是修改前的,下次遍历输出的就是修改后的)

  private static void failSafe(){
        CopyOnWriteArrayList list = new CopyOnWriteArrayList<>();

        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        for (Object o : list) {
            System.out.println(o);
        }
        System.out.println(list);
    }

    public static void main(String[] args) {
        failSafe();

    }
 
  • 底层依然是先创建一个迭代器对象

    return new COWIterator(getArray(), 0);
    
  • 在这个迭代器构造方法内部会把当前正在遍历的数组记录下拉来

    snapshot=es
    
  • 在给list添加元素时,会copyof一个新数组数组,添加的元素添加到了复制出来的新的数组里。遍历时用的是旧数组,添加时都会复制出一个新数组,两者互不干扰

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ZxWXVBKH-1652707084770)(C:Users展前进AppDataRoamingTyporatypora-user-imagesimage-20220516204317645.png)]

LinkedList

ArrayList vs LinkedList

  • ArrayLsit

    • 基于数组,需要连续的内存

    • 随机访问快(根据下标访问)

    • 尾部插入、删除性能可以,其他部分插入、删除都会移动数据,因此性能会低

    • 可以利用cpu缓存,局部性原理

      (cpu缓存读取时会把相邻的元素也读进去,备用)

  • LinkedList

    • 基于双向链表,无需连续内存
    • 随机访问慢(要沿着链表遍历)
    • 头尾插入删除性能高;(中间由于需要先沿着链表找到指定位置浪费大量时间)
    • 占用内存多

    (因为它里面是有一个个Node对象组成,每个Node又分成元素,上一个指针,下一个指针等等)

转载请注明:文章转载自 www.mshxw.com
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号