一. List集合特点、特有API
List的实现类的底层原理
- ArrayList底层是基于数组实现的:根据索引定位元素快,增删相对慢。
- LinkedList底层基于双链表实现的:查询元素慢,增删首尾元素是非常快的。
public class ListDemo01 {
public static void main(String[] args) {
// 1.创建一个ArrayList集合对象:
// List:有序,可重复,有索引的。
List<String> list = new ArrayList<>(); // 一行经典代码!多态
list.add("Java");
list.add("Java");
list.add("HTML");
list.add("HTML");
list.add("MySQL");
list.add("MySQL");
// 2.在某个索引位置插入元素。
list.add(2, "黑马");
System.out.println(list); // [Java, Java, 黑马, HTML, HTML, MySQL, MySQL]
// 3.根据索引删除元素,返回被删除元素
System.out.println(list.remove(1)); // Java
System.out.println(list); // [Java, 黑马, HTML, HTML, MySQL, MySQL]
// 4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
System.out.println(list.get(1)); // 黑马
// 5.修改索引位置处的元素: public E set(int index, E element)
System.out.println(list.set(1, "传智教育")); // 黑马
System.out.println(list); // [Java, 传智教育, HTML, HTML, MySQL, MySQL]
}
}
二. List集合的遍历方式小结
List集合的遍历方式有几种?
- 迭代器
- foreach / 增强for循环
- Lambda表达式
- for循环(因为List集合存在索引)
package com.gch.d5_collection_list;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
/**
拓展:List系列集合的遍历方式有:4种。
List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。
List遍历方式:
(1)for循环。(独有的,因为List有索引)。
(2)迭代器。
(3)foreach。
(4)JDK 1.8新技术。
*/
public class ListDemo02 {
public static void main(String[] args) {
List<String> lists = new ArrayList<>(); // 多态
lists.add("java1");
lists.add("java2");
lists.add("java3");
/** (1)for循环。 */
System.out.println("----------for循环-------------");
for (int i = 0; i < lists.size(); i++) {
String ele = lists.get(i);
System.out.println(ele);
}
/** (2)迭代器。 */
System.out.println("----------迭代器-------------");
Iterator<String> it = lists.iterator();
while (it.hasNext()){
String ele = it.next();
System.out.println(ele);
}
/** (3)foreach */
System.out.println("---------foreach--------------");
for (String ele : lists) {
System.out.println(ele);
}
/** (4)JDK 1.8开始之后的Lambda表达式 */
System.out.println("-----------Lambda表达式------------");
lists.forEach(s -> {
System.out.println(s);
});
}
}
三. ArrayList集合的底层原理
- 利用空参创建的ArrayList集合,在底层创建一个默认长度为0的数组,size等于0。
- 添加第一个元素时,底层会创建一个新的长度为10的数组,在数组当中,默认初始值都是null。
- 存满时,会扩容1.5倍
- 如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准。
- elementData是ArrayList底层数组的名称。
- ArrayList底层就是数组,而且数组有个名字,叫elementData,与此同时,Java它在底层还有一个成员变量叫size,size用来记录元素的个数,也就是集合的长度,它同时也表示了下一个元素的应存入的位置。
- 当数组存满时,它会创建一个新的数组,新数组的长度是原来的1.5倍,也就是长度为15,索引为0-14的一个数组,然后再把所有的元素全部拷贝到新数组当中。
四. LinkedList集合的底层原理
LInkedList可以完成队列结构和栈结构(双链表),双链表是队列结构和栈结构的结合体。
package com.gch.d5_collection_list;
import java.util.LinkedList;
import java.util.List;
/**
目标:LinkedList集合。
Collection集合的体系:
Collection<E>(接口)
/ \
Set<E>(接口) List<E>(接口)
/ / \ \
HashSet<E>(实现类) LinkedList<E>(实现类) Vector(实现类) ArrayList<E>(实现类)
/
LinkedHashSet<E>(实现类)
Collection集合体系的特点:
Set系列集合: 添加的元素,是无序,不重复,无索引的。
-- HashSet:添加的元素,是无序,不重复,无索引的。
-- LinkedHashSet:添加的元素,是有序,不重复,无索引的。
List系列集合:添加的元素,是有序,可重复,有索引的。
-- LinkedList: 添加的元素,是有序,可重复,有索引的。
-- Vector: 添加的元素,是有序,可重复,有索引的。线程安全(淘汰了)
-- ArrayList: 添加的元素,是有序,可重复,有索引的。
LinkedList也是List的实现类:底层是基于双链表的,增删比较快,查询慢!!
LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的
所以LinkedList除了拥有List集合的全部功能还多了很多操作首尾元素的特殊功能:
- public void addFirst(E e):将指定元素插入此列表的开头。
- public void addLast(E e):将指定元素添加到此列表的结尾。
- public E getFirst():返回此列表的第一个元素。
- public E getLast():返回此列表的最后一个元素。
- public E removeFirst():移除并返回此列表的第一个元素。
- public E removeLast():移除并返回此列表的最后一个元素。
- public E pop():从此列表所表示的堆栈处弹出一个元素。
- public void push(E e):将元素推入此列表所表示的堆栈。
小结:
LinkedList是支持双链表,定位前后的元素是非常快的,增删首尾的元素也是最快的。
所以提供了很多操作首尾元素的特殊API可的实以做栈和队列现。
如果查询多而增删少用ArrayList集合。(用的最多的)
如果查询少而增删首尾较多用LinkedList集合。
*/
public class ListDemo03 {
public static void main(String[] args) {
// LinkedList可以完成队列结构,和栈结构 (双链表)
// 双链表是栈和队列的结合体
// 1、做一个队列: queue:队列
LinkedList<String> queue = new LinkedList<>();
// 入队
queue.addLast("1号");
queue.addLast("2号");
queue.addLast("3号");
System.out.println(queue); // [1号, 2号, 3号]
// 出队
// System.out.println(queue.getFirst()); // 1号
System.out.println(queue.removeFirst()); // 1号
System.out.println(queue.removeFirst()); // 2号
System.out.println(queue); // [3号]
// 2、做一个栈 stack:栈
LinkedList<String> stack = new LinkedList<>();
// 入栈 压栈 (push) public void push(E e) { addFirst(e); }
// stack.addFirst("第1颗子弹");
stack.push("第1颗子弹");
stack.push("第2颗子弹");
stack.push("第3颗子弹");
stack.push("第4颗子弹");
System.out.println(stack); // [第4颗子弹, 第3颗子弹, 第2颗子弹, 第1颗子弹]
// 出栈 弹栈 pop public E pop() { return removeFirst(); }
// System.out.println(stack.removeFirst());
System.out.println(stack.pop()); // 第4颗子弹
System.out.println(stack.pop()); // 第3颗子弹
System.out.println(stack.pop()); // 第2颗子弹
System.out.println(stack); // [第1颗子弹]
}
}