List接口和它的实现类们
java集合框架的根接口Collection下有子接口List和Set,今天我们先来看List子接口相较于Collection根接口有什么新的特性和方法
List
java.util.List子接口:
(1)有序的
(2)元素是可以重复的
常用方法(这里只介绍较于Collection接口新增加的方法)
它继承了collection,所以collection的所有方法和操作他都有
它还增加了很多方法,这些方法都和索引(index)相关
1添加
- (1).add(int index,e element) 在index位置插入元素e
- (2)addAll(int index,collection<? Extend e> c) 在index位置插入多个元素
@Test
public void test1() {
List list = new ArrayList();
list.add("张三");
list.add(0,"李四");
for (Object object : list) {
System.out.println(object);
}
}
2.删除
- (1)remove(int index)
@Test
public void test2() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.remove(0);
for (Object object : list) {
System.out.println(object);
}
}
3.修改
- set(int index,e element)
@Test
public void test3() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.set(1, "王五");
for (Object object : list) {
System.out.println(object);
}
}
4.查
- (1)int indexOf(Obeject o)
@Test
public void test4() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
int index = list.indexOf("张三");
System.out.println(index);
Object obj = list.get(1);
for (Object object : list) {
System.out.println(object);
}
}
- (2)int lastindexOf(Object o)
@Test
public void test4() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
int index = list.lastindexOf("张三");
System.out.println(index);
Object obj = list.get(1);
for (Object object : list) {
System.out.println(object);
}
}
- (3)get(int index) 返回index位置的元素
@Test
public void test5() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
List list2 =list.subList(0, 3);
for (Object object : list) {
System.out.println(object);
}
for (Object object : list) {
System.out.println(object);
}
}
- (4)subList(int formindex,int toindex) 截取formindex位置到toindex位置的元素
@Test
public void test5() {
List list = new ArrayList();
list.add("张三");
list.add("李四");
list.add("王五");
List list2 =list.subList(0, 3);
for (Object object : list) {
System.out.println(object);
}
for (Object object : list) {
System.out.println(object);
}
}
5.遍历
- (1)toarray
- (2)foreach
- (3)Iterator
- (4)ListIterator
ListIterator是Iterator的子接口,Iterator有的,ListIterar都有.
ListIterator还增加了新的内容:遍历的方向,遍历的起始位置,Iterator只能从前往后遍历,而ListIterator可以从任意位置,从前往后,从后往前遍历
List常用实现类
Vector:旧版动态数组
-
内部实现:数组 初始化长度 10
-
继承Vector。
ArrayList:新版动态数组
-
内部实现:数组 源码中初始化为长度为0的数组,然后第一次扩容为10 之后每次扩容为1.5倍(JDK1.7 扩容为1.5倍+1)
LinkedList:
1.内部实现:链表(注意添加删除的位置,前后位置是否为空,这些都是要考虑的)
- 记录的是Node first
-
Node last
2.add添加方法
- add(xx)默认添加到链表的最后
- add(int index ,E element )
- 如果插入的位置等于size,就直接调用add方法
- 如果不等于: 先把要插入的元素包装为一个Node类型,然后再调用linkBefore方法
- linkBefore方法:判断插入的元素是不是第一个位置,是插入到first,size++
- 不是就获取到要插入的位置之前的元素和后面的元素,进行链表的连接关系的 重新赋值,实现插入
3.删除方法: - remove()方法和add方法的实现原理基本相同,只是把要删除的节点的地址连接重新
- 连接到要删除的节点的前一元素和后一元素
- 双向链表
@Test
public void test1() {
LinkedList list = new LinkedList();
list.add("a");
list.add(0,"a");
System.out.println(list);
}
1.初始化大小:10
- JDK 1.8 的时候 new ArrayList() 创建了一个长度为0的空数组
- JDK1.6的时候是直接初始化创建了一个长度为10 Object[]
- JDK 1.7的时候也是创建了一个长度为0 的空数组,但是和JDK1.8的常量不同
2.添加元素时,如果容量满了,如何扩容 - JDK1.7和JDK1.8时,因为原来是空数组,第一次先扩容为长度为10的数组,
- 如果容量还是不够,那么JDK1.7扩容为原来的1.5倍+1,JDK1.8扩容为原来的1.5倍
3.删除remove方法删除元素,容量会不会缩小
- 不会缩小,但是ArrayList可以用trimToSize调整大小为实际元素个数的大小
Stack:先入后出
-
有序的
-
方法:push()进栈,添加到栈顶
-
pop()退栈,从栈顶删除元素
-
peek() 获取到栈顶的元素
@Test
public void test1() {
Stack stack = new Stack();
stack.push("张三");
stack.push("李四");
stack.add("王五"); //因为实现了Collection接口,add()也可以用
stack.pop();
System.out.println(stack.peek());
for (Object object : stack) {
System.out.println(object);
}
}
Queue:队列
-
offer(E e) 添加到队尾
-
peek() 获取到队列的队尾元素,如果为空,返回null
-
poll() 删除队尾元素,如果为空,返回为空
面试题:Vector和ArrayList区别:
-
都是List的的实现类
-
Vector:旧版动态数组
内部实现:数组 初始化长度 10 扩容为原来的2倍
-
ArrayList:新版动态数组
内部实现:数组 源码中初始化为长度为0的数组,然后第一次扩容为10 之后每次扩容为1.5倍(JDK1.7 扩容为1.5倍+1)