1.创建
ArrayList和Linkedlist都实现了List接口
2.ArrayList
ArrayList 内部封装了一个长度可变的数组
优点
1.空间连续
2.支持随机访问性强,(get,set)
缺点:
1.中间或头插入删除时间复杂度O(N)
2.增容的代价比较大
扩容
arrayList内部是动态数组,相比长度不变的数组,有很多优点。
如果当前arraylist中元素数量大于初识容量(就会进行扩容,新的容量为旧的容量的1.5倍
扩容方式
扩容时,会以新的容量创建一个原数组的拷贝,将原数组的数据拷贝过来,原数组就会被抛弃,会被GC回收
3.LinkedList
标准库中LinkedList 底层通过双向链表实现,通过两个引用分别指向链表的第一个和最后一个元素.
标准库的LinkedList 和链表的区别
前面学的都是单向链表(面试,在线oJ),但标准库中封装的是双向链表。
时间复杂度
标准库中Linklisted(双向链表)的增删改查的时间复杂度都是o(n),除了头插头删,尾插尾删(因为是双线链表,所以不需要头部尾部不需要遍历),时间复杂度为o(1)
双向链表优点
1.内存利用率高
2.大小不固定,拓展灵活
3.头插头删,复杂度0(1)
缺点:
不支持随机访问
标准库中的方法
public static void main(String[] args) {
List<String> arrayList=new ArrayList<>();
List<String> linkedlist=new LinkedList<>();
//1.插入元素
//直接插入尾部,现需要找到尾部,尾插o(n)
//但标准库中使用了双向链表,所以复杂度为o(1)
linkedlist.add("hello");
//中间位置插入
//由于是链表,往下表插入,应先找到下表位置
//复杂度o(N)
linkedlist.add(10,"add");
//2.删除元素
//应先遍历链表,找到位置
//复杂度o(n)
linkedlist.remove("hello");
linkedlist.remove(0);
//3.查找元素,无论给定下标,还是给定值,都需要遍历,时间复杂度都是o(N)
linkedlist.indexOf("hello");
linkedlist.get(0);
//4.修改元素
//得先找到第0号元素,所以复杂度为o(N)
linkedlist.set(0,"kkk");
}
ArrayList和LinkedList区别
以下出自此处添加链接描述
- 增加元素:
1.头插/尾插
ArrayList 头插大量挪元素,时间复杂度为O(N)。 而尾插根据下标就能直接插入O(1)。
LinkedList 因为是双向链表,有节点进行记录所以时间复杂度为O(1)
2.中间位置插入
ArrayList 在中间位置插入元素,需要挪元素 ,时间复杂度为O(N)
LinkedList 在中间位置插入元素,需要遍历链表去找位置,时间复杂度也为O(N)
总结:增加元素时,LinkedList 表现更好,因为ArrayList 插入元素需要进行挪元素,而LinkedList 只需要修改地址值,而且头插和尾插速度快,所以LinkedList 表现更佳
删除元素
1.给定位置删除
ArrayList 因为有下标的存在,能很快找到位置,但是要进行挪元素,只有删除最后一个才不需要挪元素,时间复杂度为O(N)
LinkedList 删除给定位置,需要遍历链表来找到位置,所以时间复杂度为O(N)
2.给定值删除
都需要遍历来找到值,所有时间复杂度为O(N)
总结:删除元素LinkedList要优于ArrayList ,因为找到待删除的元素后,ArrayList 需要挪元素,但是LinkedList 只需要修改地址值
修改元素
1.给定位置修改
ArrayList 直接找到位置,进行修改,时间复杂度为O(1)
而LinkedList 需要遍历找位置 ,时间复杂度为O(N)
2.给定值修改
都需要遍历去修改,时间复杂度为O(N)
总结:修改元素ArrayList 因为有随机访问能力,所有在给定位置进行修改表现更好,但是二者修改给定位置速度差不多,都要遍历
查找元素
1.给定位置查找
ArrayList 有随机查找能力,时间复杂度为O(1)
LinkedList 只能遍历查找,时间复杂度为O (N)
2.给定值查找
都需要遍历查找, 时间复杂度