说一说List

269 阅读3分钟

  • ArrayList :底层是用数组实现的存储

和LinkedList相比,它的查找和访问元素的速度较快,但新增,删除的速度较慢。

特点:查询效率高,增删效率低,线程不安全。使用频率很高。

为啥线程 不安全还使用他呢?

因为我们正常使用的场景中,都是用来查询,不会涉及太频繁的增删,如果涉及频繁的增删,可以使用LinkedList,如果你需要线程安全就使用Vector,这就是三者的区别了,实际开发过程中还是ArrayList使用最多的。

  • LinkedList:是以链表实现的,插入、删除时只需要改变前后两个节点指针指向即可,底层使用的双向链表结构,有一个头结点和一个尾结点,双向链表意味着我们可以从头开始正向遍历,或者是从尾开始逆向遍历,并且可以针对头部和尾部进行相应的操作。

关于 ArrayList 扩容操作,整个过程:

就比如我们现在有一个长度为10的数组,现在我们要新增一个元素,发现已经满了,那ArrayList会怎么做呢?


第一步他会重新定义一个长度为10+10/2的数组也就是新增一个长度为15的数组。


然后把原数组的数据,原封不动的复制到新数组中,这个时候再把指向原数的地址换到新数组,ArrayList就这样完成了一次改头换面。


arrayList1.7开始变化有点大,一个是初始化的时候,1.7以前会调用this(10)才是真正的容量为10,1.7即本身以后是默认走了空数组,只有第一次add的时候容量会变成10。

ArrayList在增删的时候是怎么做的么?主要说一下为啥慢。

比如有下面这样一个数组我需要在index 5的位置去新增一个元素A

那从代码里面我们可以看到,他复制了一个数组,是从index 5的位置开始的,然后把它放在了index 5+1的位置

给我们要新增的元素腾出了位置,然后在index的位置放入元素A就完成了新增的操作了

至于为啥说他效率低,我想我不说你也应该知道了,我这只是在一个这么小的List里面操作,要是我去一个几百几千几万大小的List新增一个元素,那就需要后面所有的元素都复制,然后如果再涉及到扩容啥的就更慢了不是嘛。


ArrayList插入删除一定慢么?

取决于你删除的元素离数组末端有多远,ArrayList拿来作为堆栈来用还是挺合适的,push和pop操作完全不涉及数据移动操作。

继续打个比方,我们现在要删除下面这个数组中的index5这个位置

那代码他就复制一个index5+1开始到最后的数组,然后把它放到index开始的位置

index5的位置就成功被”删除“了其实就是被覆盖了,给了你被删除的感觉。

同理他的效率也低,因为数组如果很大的话,一样需要复制和移动的位置就大了。


ArrayList是线程安全的么?

当然不是,线程安全版本的数组容器是Vector。

Vector的实现很简单,就是把所有的方法统统加上synchronized就完事了。

你也可以不使用Vector,用Collections.synchronizedList把一个普通ArrayList包装成一个线程安全版本的数组容器也可以,原理同Vector是一样的,就是给所有的方法套上一层synchronized。