List

ArrayList

ArrayList的底层是基于动态数组实现

    transient Object[] elementData; private int size;

常用的方法

        ArrayList<String> arrayList = new ArrayList<>();    //或者ArrayList<String> arrayList = new ArrayList<>(4);arrayList.add("a"); //添加元素,在数组“尾部”添加 速度快arrayList.add(0,"c");   //添加元素,在数组“中间”添加 速度慢System.out.println(arrayList.get(0));   //获取指定下标的元素arrayList.remove("a");  //删除指定元素,通过遍历arrayList.remove(0);    //删除指定下标的元素arrayList.set(0,"b");   //修改

深入原理

初始化

ArrayList<String> arrayList = new ArrayList<>();

当调用ArrayList的无参构造器时,数组容量为0的Object数组;
当调用add()方法添加第一个数据时,才会分配容量,默认容量为10;

private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};public ArrayList() {this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;}

ArrayList<String> arrayList = new ArrayList<>(10);

当调用ArrayList的有参构造器时,会创建一个指定大小的Object数组;

    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);}}

add方法、扩容

    public boolean add(E e) {// 检查当前容量是否还可以容纳一个元素,不够则扩容ensureCapacityInternal(size + 1);  // Increments modCount!!// 添加到数组末尾// 这个语句可以分解为// elementData[size] = e;// size += 1;elementData[size++] = e;return true;}
  1. 在使用无参构造器初始化ArrayList时,便会创建一个空的数组;

  2. 当调用add()方法添加第一个数据时,便会对数组进行扩容(调用Arrays.copyOf方法),默认容量为10;

  3. 若添加数据后的容量 超出 当前数组长度,则进行扩容,扩容之后的容量为之前容量的1.5倍;


https://blog.csdn.net/zhouhengzhe/article/details/108319369

把原数组的数据,原封不动的复制到新数组中,然后把ArrauList的地址指向新数组
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fEgSRtqY-1621011446037)(https://note.youdao.com/yws/res/85142/74452E4097A64D99AAF89E5C4DF3DD38)]

1.7的时候是初始化就创建一个容量为10的数组,1.8后是初始化先创建一个空数组,第一次add时才扩容为10;

LinkedList

LinkedList是通过双向链表实现的

    transient int size = 0;transient Node<E> first;transient Node<E> last;

常用方法

LinkedList基本使用与ArrayList相同;

        LinkedList<String> linkedList = new LinkedList<>(); //注意,LinkedList没有有参构造器linkedList.add("a");linkedList.set(0,"b");  //效果等同linkedList.add(0,"c");linkedList.remove(0);linkedList.remove("c");System.out.println(linkedList.get(0));

remove

remove操作分2种,一种是根据下标删除,一种是根据元素内容删除;
根据元素内容删除时,需要遍历全部元素;

根据下标删除remove(int index)

若index < size/2,则从头遍历,否则从尾部遍历;

get(int ndex)

若index < size/2,则从头遍历,否则从尾部遍历;

ArrayList与LinkedList对比

ArrayList在使用无参构造器时,默认初始化一个容量为10的数组,当添加元素后 元素个数 大于 现有容量,则按1.5倍容量扩容,扩容 消耗性能,所以初始化时最后指定容量;

LinkedList是双向链表,当指定下标 添加、删除元素时,若index < size/2则从头节点遍历,否则从尾节点开始遍历;
当指定下标添加(不是修改指定下标元素)或者删除元素时,只需修改指针即可

ArrayList
  1. 指定下标删除元素慢 list.remove(int index)
  2. 指定下标添加元素慢 list.add(int index,E e)
  3. 指定下标查询快 list.get(int index)
LinkedList
  1. 指定下标删除元素快 list.remove(int index)
  2. 指定下标添加元素快 list.add(int index,E e)
  3. 指定下标查询慢 list.get(int index)
    需要先定位到元素所在

List与线程安全

Collections.synchronizedList()

ArrayList 与 LinkendList都不是线程安全的,但可以通过 java.util.Collections.synchronizedList(List list) 方法,获取一个线程安全的 List 实例对象;

Collections.synchronizedList(List list) 方法源码public static <T> List<T> synchronizedList(List<T> list) {return (list instanceof RandomAccess ?new SynchronizedRandomAccessList<>(list) :new SynchronizedList<>(list));
}

当传入的 list 是 ArrayList 时,返回 SynchronizedRandomAccessList 对象;传入 LinkedList 时,返回 SynchronizedList 对象。

get、set、add 等操作都添加了synchronized锁;

        public E get(int index) {synchronized (mutex) {return list.get(index);}}public E set(int index, E element) {synchronized (mutex) {return list.set(index, element);}}public void add(int index, E element) {synchronized (mutex) {list.add(index, element);}}public E remove(int index) {synchronized (mutex) {return list.remove(index);}}

CopyOnWriteArrayList


坑点

迭代器

增强for循环 的 原理就是 迭代器,这点与普通的for循环有着本质的区别;

https://juejin.cn/post/6844903569095671816

在迭代器中,不能对list进行增删操作,只能查询;
即list的add、remove会报ConcurrentModificationException异常
public static void main(String[] args) {ArrayList<String> strings = new ArrayList<String>();strings.add("a");strings.add("b");for (String string : strings) {if ("e".equals(string)) {strings.remove(string);}}}Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.ArrayList$Itr.checkForComodification(ArrayList.java:859)at java.util.ArrayList$Itr.next(ArrayList.java:831)at main.java.mo.basic.ConcurrentModificationExceptionTest.main(ConcurrentModificationExceptionTest.java:17)
Iterator实现类有2个重要的方法hasNext()和next()Iterator中有一个expectedModCount属性与list的modCount属性同步,当list执行remove时会modCount++,而Iterator中有expectedModCount却不会变化;当 Iterator调用next()方法,会使用checkForComodification做校验,modCount与 expectedModCount不同就会报错;

解决方法,使用普通的for循环,不要使用迭代器;

ArrayList、LinkedList原理相关推荐

  1. List 系列 ArrayList LinkedList CopyOnWriteArrayList Queue系列 ArrayDeque ConcurrentLinkedDeque LinkedBlo

    LinkedBlockingDeque作为一种阻塞双端队列,提供了队尾删除元素和队首插入元素的阻塞方法.该类在构造时一般需要指定容量,如果不指定,则最大容量为Integer.MAX_VALUE.另外, ...

  2. Vector ArrayList Hashtable HashMap ArrayList LinkedList

    1. Vector & ArrayList 1)  Vector的方法都是同步的(Synchronized),是线程安全的(thread-safe),而ArrayList的方法不是,由于线程的 ...

  3. java vector arraylist linkedlist用法与区别

    首先,它们是list的实现类,大致说一下vector arraylist linkedlist的区别. 1.线程安全来讲, vector是线程安全,arraylist linkedlist线程不安全. ...

  4. ArrayList,LinkedList,Vector的异同点

    先总结下ArrayList和LinkedList的区别: 1.ArrayList是实现了基于动态数组的数据结构,LinkedList基于链表的数据结构. 2.对于随机访问get和set,ArrayLi ...

  5. java linkedlist实例_Java Linkedlist原理及实例详解

    这篇文章主要介绍了Java Linkedlist原理及实例详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 定义:linkedlist属于链表结构 ...

  6. ArrayList, LinkedList, Vector - dudu:史上最详解

    ArrayList, LinkedList, Vector - dudu:史上最详解 我们来比较一下ArrayList, LinkedLIst和Vector它们之间的区别.BZ的JDK版本是1.7.0 ...

  7. ArrayList底层原理

    ArrayList底层原理 ArrayList在工作中经常用到,今天来看一下ArrayList的底层是如何实现的?在这之前,先抛出几个问题. 1.ArrayList底层实现的数据结构是什么? 2.Ar ...

  8. Collection,List,ArrayList,LinkedList集合

    Collection集合 是单例集合的顶层接口,它表示一组对象,这些对象也称为Collection的元素 lJDK 不提供此接口的任何直接实现,它提供更具体的子接口(如Set和List)实现 Coll ...

  9. ArrayList ,LinkedList,Vector,StringBuilder,StringBuffer ,String,HashMap,LinkedHashMap,TreeMap

    ArrayList ,LinkedList,Vector 区别和联系 从上面的类层次结构图中,我们可以发现他们都实现了List接口,它们使用起来非常相似.区别主要在于它们各自的实现,不同的实现导致了不 ...

  10. ArrayList LinkedList与HashMap 实现原理

    ArrayList 定义 快速了解ArrayList究竟是什么的一个好方法就是看JDK源码中对ArrayList类的注释,大致翻译如下: /** * 实现了List的接口的可调整大小的数组.实现了所有 ...

最新文章

  1. 矩阵转置 java_Java 创建矩阵并转置矩阵
  2. Android - N级树形结构实现
  3. 阿里百万级规模开源容器 PouchContainer GA 版本发布,邀您参与上海 Meetup 共话容器未来
  4. 天天象棋 残局闯关 第18关
  5. boost::spirit模块使用 phoenix 进行实际表达式评估的语法和语义操作的测试程序
  6. noip2008普及组4题题解-rLq
  7. C# 开发圆角控件的具体实现
  8. uva 11383(二分图最大权匹配)
  9. 虚拟局域网软件开源_ZeroTier虚拟局域网免费远程桌面体验--替代TeamViewer
  10. 网络监控系统安装的4种方式,安防必备
  11. Spring Boot2 整合 MyBatis 多数据源
  12. vue Cli 环境删除与重装 - 版本文档
  13. RabbitMq学习笔记002---RabbitMq在SpringBoot中的应用_配置_使用_并且设置优先级
  14. 4、Spring配置中的classpath:与classpath*:的区别
  15. android 中如何监听耳机键消息
  16. 关于利用 achartengine 画 股票 分时线
  17. matlab解决线性规划问题
  18. 项目工作说明书(SOW)
  19. 双重差分模型能做固定效应吗_双重差分法的平行趋势假定
  20. solr6.3与MySQL结合使用

热门文章

  1. 房子买贵了?房价收入比(house-price‑to‑income ratios)指标揭秘真相
  2. php合成图片系统,php图片合成
  3. win7 时间服务器地址修改,win7 时间服务器地址修改
  4. TensorFlow基础:Session(会话)
  5. swift5 修改Accessibility order读取的顺序
  6. 翻译:swift 5初始化 被忽略的Convenience便捷初始化、Required和继承
  7. 翻译:响应式编程或反应式编程 RxSwift和RxCocoa 从入门到精通 Reactive programming
  8. 对比两个文件内容差异VS Visual Studio Code
  9. mysql和oracle的时间字段区别_Oracle数据库中关于日期和时间字段类型
  10. 发布传参_Taro 1.2.9 发布,BAT 小程序、H5 与 RN 端统一框架