查阅API,看List的介绍。有序的 collection(也称为序列)。此接口的用户可以对列表中每个元素的插入位置进行精确地控制。用户可以根据元素的整数索引(在列表中的位置)访问元素,并搜索列表中的元素。与 set 不同,该列表通常允许重复的元素。
看完API,我们总结一下:
List接口:
它是一个元素存取一致的集合。例如,存元素的顺序是11、22、33。那么集合中,元素的存储就是按照11、22、33的顺序完成的)。
它是一个带有索引的集合,通过索引就可以精确的操作集合中的元素(与数组的索引是一个道理)。
集合中可以有重复的元素,通过元素的equals方法,来比较是否为重复的元素。
那么下面我们重点来学习List接口两个重点儿子 ArrayList和LinkedList类。
1.ArrayList
先来看一下ArrayList中特有方法。
ArrayList<E>中的方法(这里的E可以当作为Object类来理解,我这里举例使用String类型):
public boolean add(E e):添加元素到列表末尾
public void add(int index, E element):将指定元素添加到指定索引位置,该位置原有的元素及之后元素会后移
public E get(int index):将指定索引位置的元素取出
public E set(int index, E element):将指定位置的元素设置成新的值,并且返回该索引原有的值
public E remove(int index):将指定索引位置的元素删除,并且返回要删除的元素
public class ArrayListDemo01 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("张三");
al.add("李四");
//1.将指定元素添加到指定索引位置
al.add(1,"王五");
System.out.println(al);
//2.将指定索引位置的元素取出
System.out.println(al.get(2));
//3.将指定位置的元素设置成新的值,并且返回该索引原有的值
System.out.println(al.set(1,"赵六"));
//4.将指定索引位置的元素删除,并且返回要删除的元素
al.remove(0);
System.out.println("经过上述一系列操作后集合中元素:"+al);
}
}
1.1 ArrayList原理
ArrayList底层原理
1.ArrayList从名字上推断(Array)底层使用的是数组结构
2.new ArrayList()的时候,底层会创建一个空数组,即Object[] elementData =new Object[0];
3.当首次调用add方法的时候,底层会开辟一个默认容量为10的Object数组
此时,Object[] elementData = new Object[10],用来存储第一个元素。
对ArrayList<String> al = new ArrayList<>();进行Debug强制进入,如下图:
而不难发现,这里的elementDate是一个Object类型的数组,且初始化为{ }。该数组的默认容量为10,即:
再增加元素之后,直接打印集合会调用重写后的toString方法,如下图,可以看到,创建了一个迭代器,如果! it.hasNext()为true,即没有下一个元素,直接打印[ ]。否则往下执行,会创建一个StringBuilder容器,先把“【”加上,再遍历判断当前元素e是集合本身还是下一个普通元素,如果是普通元素就直接调用append追加再后面,最后跟上“】”,完成元素的添加。
ArrayList的扩容原理类似于StringBuilder,这里不再展示具体操作,可以去参考StringBuilder的扩容解释,下面用图来理解ArrayList如何扩容:
1.2 ArrayList特点
1.集合中元素有索引,有顺序,可以存储重复元素
2.ArrayList集合增删慢,查询快
a.查询快:因为ArrayList底层是一个数组,而数组有索引,我们根据索引可以直接取出元素
集合索引 0 1 2 3 4 ... 9
ArrayList元素: "abc" "def" "ghk" null null ... null
获取"ghk":根据索引直接可以取出元素 get(2)
b.增删慢:如果我们要增删一个元素,会导致这个元素后面的所有元素往前或者往后挪动,可能会移动大量元素,导致ArrayList增删效率低
集合索引 0 1 2 3 4 ... 9
ArrayList元素: "abc" "def" "ghk" null null .... null
添加一个"ml"到0索引位置 "ml" "abc" "def" "ghk" null ... null
当我们添加一个元素的时候,该元素之后的元素都要依次往后移动一个位置
集合索引 0 1 2 3 4 ... 9
ArrayList元素: "abc" "def" "ghk" null null .... null
删除"abc" "def" "ghk" null null null .... null
当我们删除一个元素的时候,该元素之后的元素都要依次往前移动一个位置
也可以看图片理解:
1.3 ArrayList的三种遍历方式
对于ArrayList集合的遍历,有常用的三种方法。分别是:迭代器遍历、(特有遍历方式)索引遍历、增强for遍历。
首先看第一种,迭代器遍历:
public class ArrayListDemo03 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("abc");
al.add("def");
al.add("qwe");
Iterator<String> iterator = al.iterator();
while(iterator.hasNext()){
System.out.println(iterator.next());
}
}
}
查看API发现ArrayList中有迭代器方法,那就可以使用迭代器来遍历集合中的元素,使用集合对象al来创建迭代器,再使用迭代器的hasNext( )判断是否有下一个元素,使用next()打印下一个元素,针对于迭代器的这两个方法:
其实刚开始的时候hasNext()的指针指向的是第一个元素上方,此时判断存在下一个元素的时候,指针移动指向第一个元素。如图:
当hashNext( )指向最后一个元素的时候,再进行判断就会返回false值,此时循环就停止了。也就循环遍历结束。
最后运行结果图:
再看第二种方式:索引遍历,也是ArrayList特有的遍历(其他集合没有索引)。
public class ArrayListDemo03 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("abc");
al.add("def");
al.add("jdk");
for (int i = 0; i < al.size(); i++) {
System.out.println(al.get(i));
}
}
}
这里的size方法和get方法上面提到过,size获取集合中有效元素数,get方法可以传入索引来返回指定的元素。
运行结果:
最后看第三种:增强for遍历
public class ArrayListDemo03 {
public static void main(String[] args) {
ArrayList<String> al = new ArrayList<>();
al.add("张三");
al.add("李四");
al.add("王五");
for (String element:al){
System.out.println(element);
}
}
}
增强for语法:for(所遍历的数据类型 变量名:所遍历集合),所以直接输出结果为:
其实对于ArrayList存储自定义引用类型,存储的仍是地址值,而并非对象本身。(这里省略了部分代码)直接可以看下图理解:
2.LinkedList
2.1 LinkedList原理
LinkedList是基于一种双向链表的实现。LinkedList 类还为在列表的开头及结尾 get、remove 和 insert 元素提供了统一的命名方法,所有操作的执行都与双向链表的预期相同。可以看下图来理解LinkedList的实现原理。
再来说说LinkedList<E>中特有的方法:
public void addFirst(E e):向集合的开头位置添加元素
public void addLast(E e):向集合的末尾添加元素
public E getFirst():获取集合头部的元素
public E getLast():获取集合尾部的元素
public E get(int index):取出指定位置的元素
public E removeFirst():移除头部元素,并且返回当前被删除的元素
public E removeLast():移除尾部的元素,并且返回当前被删除的元素
public class LinkedListDemo01 {
public static void main(String[] args) {
LinkedList<String> ll = new LinkedList<>();
ll.add("abc");
ll.add("def");
//1.每一次都添加到最前面
ll.addFirst("ghk");
System.out.println(ll);//[ghk, def, abc]
//2.向集合的末尾添加元素
ll.addLast("poo");
System.out.println(ll);//[ghk, abc, def, poo]
//3.获取集合头部的元素
System.out.println(ll.getFirst());//ghk
System.out.println(ll);//[ghk, abc, def, poo]
//4.获取集合尾部的元素
System.out.println(ll.getLast());//poo
System.out.println(ll);//[ghk, abc, def, poo]
//5.取出指定位置索引元素
System.out.println(ll.get(1));//abc
System.out.println(ll);//[ghk, abc, def, poo]
//6.移除头部元素,并且返回当前被删除的元素
System.out.println(ll.removeFirst());//ghk
System.out.println(ll);//[abc, def, poo]
//7.移除尾部的元素,并且返回当前被删除的元素
System.out.println(ll.removeLast());//poo
System.out.println(ll);//[abc, def]
}
}
2.2 LinkedList特点
这里主要分析LinkedList基于双向链表的方式实现元素的增加删除查询。
LinkedList增加或删除元素,效率相对于ArrayList较高, ArrayList每次添加 或删除 动作,可能需要移动大量的元素而LinkedList只需要改变元素记录的地址值就可以了
尽管双向链表查询既能从头开始找,也能从尾开始找,但是LinkedList 查询效率相对于ArrayList 较慢,因为ArrayList可以根据索引直接取出元素,而LinkedList需要 顺链 或 逆链 杳找,
具体看图理解:
3.集合的另一种初始化方式
对于集合的初始化方式,我们一般写 ArrayList<String> al = new ArrayList<>();后再使用add方法增添元素,al.add("abc");,而另一种初始化方式我们也应能看懂和使用,如下:
public class ArrayListDemo02 {
public static void main(String[] args) {
//1.一般初始化方式
ArrayList<String> al = new ArrayList<>();
al.add("abc");
al.add("def");
System.out.println(al);
//2.双大括号形式初始化集合
ArrayList<String> al02 = new ArrayList<>(){
{
add("abc");
add("def");
}
//相当于打印对象,但是最终还是会调用toString方法
};
System.out.println(al02);
System.out.println(al02.getClass());
}
}
运行结果:
代码中的1.中的初始化方式就是我们常用的,2.中的大括号形式就是另一种,对于理解,我们可以把大括号形式的初始化看成是:
class ArrayListDemo02$1 extends ArrayList<String>{
{
//构造代码块
add("abc");
add("def");
}
//继承了ArrayList的toString方法
}
ArrayList<String> al = new ArrayListDemo02$1();
这种初始化方式相当于底层创建了一个名为 ArrayListDemo02$1 继承了Arraylist,然后通过父类ArrayList实现子类 ArrayListDemo02$1的对象al,我们可以通过getClass( )方法来验证一下:
打印输出的class arraylist01.ArrayListDemo02$1也验证了我们的说法,对象al02引用指向对象使用的类是ArrayListDemo02$1,而不是直接输出的ArrayList,于我们前面所学到的匿名内部类的思想一样。针对于运行的原理,其实当我们new对象的时候,会先走构造代码块,构造代码块中有添加元素的方法,相当于把元素添加到集合中。
标签:体系,ArrayList,元素,List,al,add,println,public From: https://blog.csdn.net/2301_77206753/article/details/142577996