集合框架库List接口 -- ArrayList、LinkedList、Vector、Stack

简单介绍List接口下的四个集合

List接口:是Collection接口的子接口,也是最常用的接口。此接口对Collection接口进行了大量的扩充,存储的内容是允许有重复,允许有null并且有序的。有序为插入的顺序。

一、ArrayList

1. ArrayList接口特性

(1)ArrayList继承的类:
implements List, RandomAccess, Cloneable, java.io.Serializable
List:存放单值,内容允许为null允许重复,插入有序(插入的顺序)插入的第一元素实际上就存放到 了数组的0号下标。
RandomAccess:表示ArrayList可被随机访问
Cloneable:集合可以使用clone方法
Serializable:可序列化,表示ArrayList可以进行可序列化操作

(2)在ArrayList接口里面有内部类Itr和ListItr继承了这些类
private class Itr implements Iterator
可以使用迭代器遍历的,从前向后进行遍历。
private class ListItr extends Itr implements ListIterator
是Iterator接口的子接口,可以进行双向输出
Iterable:ArrayList可以使用迭代器进行遍历

(3)arraylist是对数组这种数据结构的封装,所以Arraylist也支持随机访问。

2. ArrayList的基本使用

添加:
add(元素) 有序添加
add(int index,元素) 可以指定插入位置
批量添加:
addAll(Collection c) 传一个单值类型的集合
addAll(int index, Collection c) 在index下标添加一个单值类型的集合

删除:
remove(int index) 删除index下标下对应的元素
remove(Object o) 删除集合中的o元素
批量删除:
removeAll(Collection c) 删除包含在单值集合c中的值
retainAll(Collection c) 删除不包含在c集合中的元素

修改:
set(int index, E element)

查找:
get(int index); 不能越界 0<=index

3. ArrayList–交集、并集、差集、子集

(1)交集:两个集合的共同部分
实现方法:list.retainAll(list2);
(2)并集:两个集合相并
实现方法:一个集合+(另一个集合的-交集)
arrList2.removeAll(arrList1); //集合2-交集
list3.addAll(arrList1);
list3.addAll(arrList2);
(3)差集:一个集合-交集
arrList1.removeAll(arrList2);
(4)子集:subList();
subList(int fromIndex, int toIndex)
List ll = list2.subList(1,3); //ll集合为list2中在下标区间[1,3)之间的元素,为list2的一子集合

二、LinkedList

1. LinkedList接口特性

(1)底层结构:双向链表
LinkedList:即是List接口的集合,又是queue接口下的集合
(2)实现的接口:
implements List, Deque, Cloneable, java.io.Serializable
List:存放单值,内容允许为null允许重复,插入有序(插入的顺序)插入的第一个元素为双向链表的头结点
Deque:queue的子接口,双端队列接口,即双端队列,是一种具有队列和栈的性质的数据结构
Cloneable:集合可以使用clone方法
Serializable:可序列化,表示LinkedList可以进行可序列化操作
(3)内部类:
private class ListItr implements ListIterator
是Iterator接口的子接口,可以进行双向输出
private class DescendingIterator implements Iterator
可以使用迭代器遍历的,从前向后进行遍历。

2. LinkedList基本使用

LinkedList linkedList = new LinkedList<>();
添加元素
linkedList.add(i);
修改元素
linkedList.set(9,999);
添加元素
linkedList.add(2,88);
删除
linkedList.remove(3);

3. LinkedList和ArrayList的一大区别

从方法进行对比

  1. get(int index) 方法:通过下标返回对应的元素
    (1)ArrayList为底层是数组,可以直接通过下标去拿对应的元素
    (2)LinkedList为双向链表,只能一边遍历一边计数,直到计数到index位置上,然后将数据返回,因此LinkedList不适合做随机访问操作。
  2. add(int index); remove(int index);
    (1)ArrayList在实现的时候,有大量的数据移动和拷贝,比如在指定下标进行添加,该下标及后面的元素需要向后移动,删除元素后需要向前移动,扩容涉及到数据拷贝,效率低,时间复杂度为O(n),不适合做随机的插入和删除。
    (2)LinkedList插入和删除时不需要移动数据,只需要改节点的前驱和后继地址,所以LInkedList适合做数据的插入和删除

总结:
ArrayList适合随机访问,不适合插入和删除操作
LinkedList适合插入删除操作,不适合随机访问

三、Vector

1.Vector接口特性

(1)Vector:实现类似动态数组的功能,线程安全。
特点:与ArrayList特点几乎一样
(2)实现类:
implements List, RandomAccess, Cloneable, java.io.Serializable
List:存放单值,内容允许为null允许重复,插入有序(插入的顺序)插入的第一个元素为双向链表的头结点
RandomAccess:表示ArrayList可被随机访问
Cloneable:集合可以使用clone方法
Serializable:可序列化,表示LinkedList可以进行可序列化操作
(3)内部类:
private class Itr implements Iterator
可以使用迭代器遍历的,从前向后进行遍历。
final class ListItr extends Itr implements ListIterator
是Iterator接口的子接口,可以进行双向输出

2.Vector基本操作

添加:
add(E item);
add(int index, E item);
删除:
remove(object o);
remove(int index);
获取:
get(int index);
修改:
set(int index, E item);

四、Stack

1.Stack接口特性

栈:利用vector实现了一个栈,线程安全。
class Stack extends Vector

2.Stack基本使用

添加:push();
取出栈顶元素并删除:pop();
取出栈顶元素不删除:peek();

五、总结

1. LinkedList和ArrayList的区别

属于List接口下的集合
a. 底层数据结构:ArrayList数组 LinkedList双向链表
b. 使用场景:
LinkedList更适合添加删除方法比较频繁的操作,不会有数据的移动
而ArrayList随机的添加删除时,会造成数据的移动,导致效率过低。ArrayList适合于随机访问操作比较频繁的。
注意:随机
c. 源码实现:
ArrayList底层结构为数组,初始容量为0,第一次扩容10,之后1.5倍扩容
LinkedList无容量的概念两者都实现了List接口,数据可以为null,可重复,且为插入有序

2. ArrayList和Vector的区别

(1)使用没有区别
(2)源码上:
a. 底层数据结构:都是数据
b. 构造函数:初始化时机
ArrayList初始数组大小为空,在添加第一个元素时,容量变为10;
Vector的初始数组容量为10;
c. grow():
ArrayList:第一次扩容容量为10,之后呈1.5倍扩容
Vector:如果capacityIncrement不大于0的话,Vector 2倍扩容
如果capacityIncrement小于0,Vector容量扩大capacityIncrement个
默认情况下Vector为 2 倍扩容,默认情况下capacityIncrement为0;
如果增长因子大于0,扩大增长因子个大小;
capacityIncrement:增长因子
扩容方法:Vector更合理
ArrayList 每次扩容为1.5倍,但Vector可控制增长因子,可以有效的避免空间浪费。
d. 线程安全:
Vector中所有的方法都添加了synchronized锁,所以Vector是线程安全的。
ArrayList没有加锁处理所以Vector是线程不安全的。

3. 什么时候该用vector,什么时候用ArrayList

使用场景:线程安全问题
多线程条件下需要考虑线程安全问题选择Vector,如果不考虑则使用ArrayList
不用考虑线程安全问题时为什么不使用Vector:加锁操作非常耗时

4. 什么时候该用LinkedList,什么时候用ArrayList

LinkedList更适合添加删除方法比较频繁的操作,因为不会有数据的移动
ArrayList随机的添加删除时,会造成数据的移动,导致效率过低。ArrayList适合于随机访问操作比较频繁的。

5. 数组和集合的区别

a. 数组是静态的,集合是动态的;
b. 集合功能更全面(例如:下标是否越界)
c. 数组需要指定类型Integer[] arr,存储的数据必须是这个类型;
集合创建时不需要(类型可有可无)如果有存储类型必须为这个类型,如果没有存储数据类型任意。
d. 数组在指定类型时既可以使用普通类型,也可以使用引用类型;
Integer[] arr int[] brr
集合只能使用引用类型。
e. 数组的优势:数组是JAVA的一个内置类型,数组效率更高。
f. 使用场景
对元素的数量有一定的判断,并且轻易不会发生改变,存储好的数据后续不会有太多复杂的操作。集合与之相反。

你可能感兴趣的:(JavaSE)