文章目录
1. List 接口
1.1 概述
Collection
集合可以分为两大类:List
和Set
;- 其中
List
集合,操作者可以控制添加 元素的位置,用户可以根据 元素的索引 来访问元素。
1.2 List 特点
- 元素有序。
- 可以存放重复的元素。
- 元素有下标(索引)。
1.3 List 方法
- 你会发现
List
接口中的方法方法中有很多都是Collection
的接口中的方法。 List
,也有自己的独特方法。- 是不是发现了点什么? List中大多数方法都是可以 按照索引进行操作 的。
名称 | 作用 |
---|---|
void add(E e) | 向集合中添加元素 |
void add(int index,Object element) | 根据索引,在指定位置添加元素 |
boolean contains(Object o) | 如果此列表包含指定的元素,则返回 true |
Object get(int index) : | 获取指定索引处元素,从0开始 |
E set(int index, E element) | 根据索引,替换该位置元素 |
int indexOf(Object o) | 返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。 |
int lastIndexOf(Object o) | 返回此列表中指定元素的最后一次出现的索引,如果此列表不包含元素,则返回-1。 |
Object remove(int index) | 根据索引删除元素 |
boolean remove(Object o) | 从列表中删除指定元素的第一个出现(如果存在)(可选操作)。 |
Object set(int index,Object element) | 根据索引修改元素 |
List<E> subList(int fromIndex, int toIndex) | 从集合中截取,列表中指定的 fromIndex (含)和 toIndex(不含)之间的新集合。 |
ListIterator listIterator(int index) | 从列表中的指定位置开始,返回列表中的元素(按正确顺序)的列表迭代器。 |
ListIterator listIterator() | 返回列表中的列表迭代器(按适当的顺序) |
1.4 课堂练习
1.4.1 练习:List 方法测试
- 根据方法特点,测试List常用方法。
- 有自己的方法也有
Collection
方法。
- 有自己的方法也有
public class Test_List {
public static void main(String[] args) {
//1.创建对象测试方法。
List<String> list = new ArrayList();//右边的<>可以不写。1.8特性自己动推断。
//2 测试共同方法
//2.1 添加元素
list.add("张楚岚");
list.add("宝儿姐");
list.add("徐三");
System.out.println(list);//[张楚岚, 宝儿姐, 徐三]
//list.clear(); //清空集合
//2.2 contains(); 是否包含该元素,返回boolean类型
System.out.println("contains: "+ list.contains("宝儿姐"));
//2.3 isEmpty(); 判断集合中是否包含元素。
System.out.println("isEmpty: "+ list.isEmpty());
//3 测试独特方法List方法
//add(index,e); 在指定位置添加元素。
list.add(2,"徐四"); //索引元素就是输出顺序.
System.out.println(list);//[张楚岚, 宝儿姐, 徐四, 徐三]
//3.1 get()获取指定索引处元素。
System.out.println("get(): "+list.get(1));
//3.2 indexof();返回此列表中指定元素的第一次出现的索引,如果此列表不包含元素,则返回-1。
// lastindexof(); 最后一次出现的元素的索引。
list.add("宝儿姐");//再次向集合中添加元素。为了测试indexof()
System.out.println("indexof: "+list.indexOf("宝儿姐"));
System.out.println("lastindexof: "+list.lastIndexOf("宝儿姐"));
//3.3 remove(int index): 移除对应索引的元素。
System.out.println("remove(): "+list.remove(0));//移除第一个索引元素
System.out.println(list);
//3.4 remove(object):移除一个出现的元素。
System.out.println(list.remove("宝儿姐"));
System.out.println(list);
//3.5 set(index ,e):相当于修改操作,在指定位置修改元素
System.out.println("set(): "+list.set(0,"张楚岚"));
System.out.println(list);
//3.6 sublist(fromindex toindex): 包含开始,不包含结尾,截取一个新的集合。
List<String> list1 = list.subList(1, 2);
list1.add("徐四");//向新集合中添加元素
System.out.println(list1);//[徐三, 徐四]
/*
*集合间的操作,当两个集合不一样时,如list1 和list,
*/
System.out.println(list);
//System.out.println(list1.removeAll(list));//删除的是list
System.out.println(list1.retainAll(list)); //是保留的意思list集合中元数。删除的是list1中的。
System.out.println(list1);
}
}
-
输出结果:
[张楚岚, 宝儿姐, 徐三] contains: true isEmpty: false [张楚岚, 宝儿姐, 徐四, 徐三] get(): 宝儿姐 indexof: 1 lastindexof: 4 remove(): 张楚岚 [宝儿姐, 徐四, 徐三, 宝儿姐] true [徐四, 徐三, 宝儿姐] set(): 徐四 [张楚岚, 徐三, 宝儿姐] [徐三, 徐四] [张楚岚, 徐三, 徐四, 宝儿姐] false [徐三, 徐四]
1.4.2 练习:迭代器测试
- 迭代器的使用。
List
迭代器很丰富因为有索引,你可以使用iterator() ,listIterator()
,也可以是用增强foreach
,for循环
都可以。
ublic class Test_List2 {
public static void main(String[] args) {
/*
主要是测试迭代器使用,即遍历。
foreach()
for()
iterator()
listIterator()
listIterator(int index)
*/
List<String> list = new ArrayList();//右边的<>可以不写。1.8特性自己动推断。
//1 添加元素
list.add("张楚岚");
list.add("宝儿姐");
list.add("灵玉师兄");
list.add("老天师");
//1种遍历方式 for循环 步长就是 list.size()获取结合中的元素。
for (int i=0;i<list.size();i++){
String s = list.get(i);//集合名称.get()根据指定索引获取集合。
System.out.println(s);
}
//2种,使用 foreach 增强循环 缺点:无法操作索引,只能从头到尾输出。
//foreach(遍历数据类型 变量名称:集合)
System.out.println("---------------------------华丽分割线2---------------------------");
for (String s_resault:list) {
System.out.println(s_resault);
}
System.out.println("---------------------------华丽分割线3---------------------------");
//3种,使用collection中的遍历方式 iterator()
Iterator<String> it = list.iterator();
while (it.hasNext()){ //判断集合中是否还要下一个元素
String next = it.next(); //获取下一个元素
System.out.println(next);
}
System.out.println("---------------------------华丽分割线4---------------------------");
//4种,使用自己的迭代器,listiterator(); 这个迭代器还有自己的方法可以(逆向操作:即反向输出)。
ListIterator<String> it2 = list.listIterator();
while (it2.hasNext()){
String next = it2.next();
System.out.println(next);
}
System.out.println("---------------------------反向操作---------------------------");
//反向操作,一般情况下不用!
while (it2.hasPrevious()){
String previous = it2.previous();
System.out.println(previous);
}
System.out.println("---------------------------华丽分割线5---------------------------");
ListIterator<String> iterator = list.listIterator(2);//相当于从第二个索引开始
while (iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
}
}
输出结果:
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线2---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线3---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------华丽分割线4---------------------------
张楚岚
宝儿姐
灵玉师兄
老天师
---------------------------反向操作---------------------------
老天师
灵玉师兄
宝儿姐
张楚岚
---------------------------华丽分割线5---------------------------
灵玉师兄
老天师
2. ArrayList 实现类
2.1 概述
- 在
java.util.ArrayList
包下,底层是数据结构是 数组。- 元素有序,有下标(索引),可以重复。
- 有集合的特点可以扩容,但是第一次初始化的时以 “0”的空数组,
- 当初次
add()
时,增加元素时,第一次扩容为10,然后每次以前一次的1.5倍扩容。(相当于一个懒加载模式)。
- 当初次
ArrayList
因为底层是数组结构,- 特点: 查询快(因为有索引),相对来说 增加和删除效率低。
- 特点: 查询快(因为有索引),相对来说 增加和删除效率低。
2.2 创建对象
- Api提供的创建对象的方式有3种,由于是实现类,可以直接创建对象。
1.ArrayList() ; 推荐第一种!
构造器创建对象。
2.ArrayList(Collection<? extends E> c);
构造一个包含指定集合的元素的列表,按照它们由集合的迭代器返回的顺序。
3.ArrayList(int initialCapacity);
构造具有指定初始容量的空列表。
2.3 练习:ArrayList()
- 虽然之前练习过,要注意程序由上到下执行,方法执行后会改变元素个数。
- 重复的事情,认真做!
public class Test_ArrayList {
public static void main(String[] args) {
ArrayList<Integer> a = new ArrayList<>();
a.add(1);
a.add(2);
a.add(4);
a.add(5);
System.out.println(a);
//集合2
ArrayList<Integer> a1 = new ArrayList<>();
a1.add(100);
a1.add(200);
a1.add(300);
//测试arraylist方法,大部分都见过。
a.add(2,3); //在索引2的位置插一个3。
System.out.println(a);
//contains():是否包含此元素
System.out.println("contains: "+a.contains(1));
//clone():浅拷贝返回一个Objct的数组。相当于拷贝了引用地址值。
// 使用时需要强制转换(ArrayList<Interger>)clone;
Object clone = a.clone();
System.out.println("clone: "+clone);
//get():通过索引获取元素
System.out.println("get(): "+a.get(2));
//indexof()和lastindexof();第一个出现和最后一个出现
a.add(1);//想集合中添加元素 1。为了测试
System.out.println("indexof(): "+a.indexOf(1));
System.out.println("lastindexof(): "+a.lastIndexOf(1));
//isEmpty();判断集合是否包含元素
System.out.println("isEmpty(): "+a1.isEmpty());
//remove();删除集合指定的元素有两种情况,可以根据索引删除,也根据元素删除;
System.out.println("remove(): "+a.remove(1)); //返回索引值
System.out.println("remove(object o): "+a.remove(1));//返回索引值
//size():返回集合元素个数
System.out.println("size() :"+a.size());
//get():根据下标获取元素
System.out.println("get() : "+a.get(0));
System.out.println("---------------------华丽分割线---------------------");
/*集合之间的操作*/
//addAll(collection<>); 相当于将(a1)集合中的元素按照位置插入到a集合中。
//addAll(index collection<>); 相当于将(a1)集合中的元素按照位置插入到a集合中。
System.out.println(a.addAll(a1));
//System.out.println("addAll(): "+a);
System.out.println(a.addAll(2, a1));
System.out.println("addAll(): "+a);
//a1.clear(); //清除集合中的元素。
System.out.println("---------------------华丽分割线---------------------");
/*
遍历集合ArrayList();
*/
//1.for循环
for (int i=0;i<a.size();i++){ //a.size():相当于集合步长
Integer i_resault = a.get(i); //get()根据下标获取元素。
System.out.println(i_resault);
}
System.out.println("---------------------华丽分割线---------------------");
//2.种遍历方式,用自己的迭代器iterator()
Iterator<Integer> iterator = a.iterator();
while (iterator.hasNext()){
Integer next = iterator.next();
System.out.println(next);
}
}
}
-
输出结果:
[1, 2, 4, 5] [1, 2, 3, 4, 5] contains: true clone: [1, 2, 3, 4, 5] get(): 3 indexof(): 0 lastindexof(): 5 isEmpty(): false remove(): 2 remove(object o): 3 size() :4 get() : 1 ---------------------华丽分割线--------------------- true true addAll(): [1, 4, 100, 200, 300, 5, 1, 100, 200, 300] ---------------------华丽分割线--------------------- 1 4 100 200 300 5 1 100 200 300 ---------------------华丽分割线--------------------- 1 4 100 200 300 5 1 100 200 300
3. LinkedList 实现类
3.1 概述
- 底层不同于
ArrayList
数组结构,LinkedList
底层是 链表结构,- 而且是 双向链表,有序,逻辑索引,不不同于ArrayList 下标索引,(这句话怎么理解?)。
- 所谓的链表:如生活中的自行车链条,一个 node(节点) 连接另一个节点。
- 那 双向链表,LinkedList中维护了两个属性
first
和last
分别指向 首节点和尾结点。
- 那 双向链表,LinkedList中维护了两个属性
- 听起来比较懵咱们走一波小图画!
- 上图总结:
Linkedlist
底层是双链表结构,每一个连接点称为Node(节点),封装着三个属性:分别是存储元素,上一个节点的地址值,下一个节点的地址值。- 其实
Linkedlist
是不同于Arraylist那样的索引,LinkedList 可以理解为 “逻辑索引”(每一次查询相当于一次for循环),每一次查询,都是从头开始一直查询到尾。 - 首节点和尾节点,会连接不同于其他节点,二者很近。所以针对首尾操作提供了大量的api。
- 这样的特殊结构就相对于
ArrayList
来说,特点: 查询慢,插入,删除快。
- 源码分析。
- Node节点是一个类
private static class Node<E> {
E item; //存储对象
Node<E> next; // 当前节点的next指针,指向下一个next
Node<E> prev; // 当前节点的prev指针,指向上一个、prev
Node(Node<E> prev, E element, Node<E> next) {
this.item = element;
this.next = next;
this.prev = prev;
}
}
transient int size = 0; //初始化大小
/**
* Pointer to first node.
* Invariant: (first == null && last == null) ||
* (first.prev == null && first.item != null)
*/
transient Node<E> first; //告诉你哪个是首节点,并指向首节点
/**
* Pointer to last node.
* Invariant: (first == null && last == null) ||
* (last.next == null && last.item != null)
*/
transient Node<E> last; //指向尾节点,告诉你哪个是尾节点
/**
* Constructs an empty list.
*/
public LinkedList() {
}
3.2 创建对象
-
LinkedList
创建对象的方式:- 通过构造方法。
new LinkedList() ; 通过构造函数,直接new 创建对象。
3.3 常用方法介绍
LinkedList
也实现了List
接口,那么List
有的方法,它也会,但是也有自己独特的方法。LinkedList
针对首尾元素的 添加和删除 ,提供了很多套API的方法,- 只需要记住一套 使用即可。
常用方法 | 作用 |
---|---|
void add(int index, E element) | 在此列表中的指定位置插入指定的元素。 |
void addFirst(E e) | 在该列表开头插入指定的元素。 |
void addLast(E e) | 将指定的元素追加到此列表的末尾 |
E element() | 检索但不删除此列表的头(第一个元素)。 |
E get(int index) | 返回此列表中指定位置的元素。 |
E getFirst() | 返回此列表中的第一个元素。 |
E getLast() | 返回此列表中的最后一个元素。 |
E removeFirst() | 从此列表中删除并返回第一个元素。 |
E removeLast() | 从此列表中删除并返回最后一个元素。 |
boolean offer(E e) | 将指定的元素添加为此列表的尾部(最后一个元素)。 |
boolean offerFirst(E e) | 在此列表的前面插入指定的元素。 |
boolean offerLast(E e) | 在该列表的末尾插入指定的元素。 |
E peek() | 检索但不删除此列表的头(第一个元素)。 |
E peekFirst() | 检索但不删除此列表的第一个元素,如果此列表为空,则返回 null 。 |
E peekLast() | 检索但不删除此列表的最后一个元素,如果此列表为空,则返回 null 。 |
E poll() | 检索并删除此列表的头(第一个元素)。 |
E pollFirst() | 检索并删除此列表的第一个元素,如果此列表为空,则返回 null 。 |
E pollLast() | 检索并删除此列表的最后一个元素,如果此列表为空,则返回 null 。 |
3.4 练习:LinkedList()
- 主要针对首尾添加元素,提供了多套添加首尾元素的方法,只需要掌握一套即可。其他了解。
- 为什么没有索引还提供了一个
get(int index)
方法查询。
- 为什么没有索引还提供了一个
public class Test_LinkedList {
public static void main(String[] args) {
//1.创建对象
LinkedList<String> linkedList = new LinkedList();
linkedList.add("钢铁侠");
linkedList.add("雷神");
linkedList.add("鹰眼");
linkedList.add("绿巨人");
System.out.println(linkedList);//[钢铁侠, 雷神, 鹰眼, 绿巨人],从添加输出来看,集合有序。
//2.测试LinkedList方法
//2.1 void add(int index, E element):根据索引添加指定元数。
linkedList.add(2,"美国队长");//向指定索引处,添加元素。
System.out.println(linkedList.get(3));; //根据索引获取指定元数。
System.out.println(linkedList);
//2.2 addFirst()和 addLast(),在头插入元素和在尾插入元素
linkedList.addFirst("冬兵");//插入首元素
linkedList.addLast("黑豹");// 插入尾元素
System.out.println(linkedList);
//2.3 getFirst()和 getLast(),获取首尾元素
System.out.println(linkedList.getFirst());
System.out.println(linkedList.getLast());
//2.4 E element();
System.out.println(linkedList.element());//也是返回第一个元素,底层调用getFirst();
//2,5 removeFirst()和 removeLast() 移除第一个和最后一个元素
System.out.println(linkedList.removeFirst());//返回移除元素
System.out.println(linkedList.removeLast());// 返回移除元素
System.out.println(linkedList);
System.out.println("-----------------华丽的分割线------------------");
// 3测试其他方法
LinkedList<String> linkedList2 = new LinkedList();
linkedList2.add("大娃");
linkedList2.add("二娃");
linkedList2.add("三娃");
//3.1 查询方法 peek()
System.out.println(linkedList2.peek());// 检索第一个
System.out.println(linkedList2.peekFirst());
System.out.println(linkedList2.peekLast());
//3.2 添加方法 offer()
System.out.println(linkedList2.offer("金刚葫芦娃"));//末尾插入元素
System.out.println(linkedList2.offerFirst("四娃"));
System.out.println(linkedList2.offer("五娃"));
System.out.println(linkedList2);
//3.3 移除方法 poll()
System.out.println(linkedList2.poll());//移除第一个元素
System.out.println(linkedList2.pollFirst());//移除第一个元素
System.out.println(linkedList2.pollLast());//移除第最后一个元素
System.out.println(linkedList2);
System.out.println("-----------------华丽的分割线------------------");
//4.遍历使用 foreach 效率高!
for (String slist:linkedList2) {
System.out.println(slist);
}
//5.也可以用iterator迭代遍历
Iterator<String> iterator = linkedList2.iterator();
while (iterator.hasNext()){
String next = iterator.next();
System.out.println(next);
}
}
}
输出结果:
[钢铁侠, 雷神, 鹰眼, 绿巨人]
鹰眼
[钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人]
[冬兵, 钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人, 黑豹]
冬兵
黑豹
冬兵
冬兵
黑豹
[钢铁侠, 雷神, 美国队长, 鹰眼, 绿巨人]
-----------------华丽的分割线------------------
大娃
大娃
三娃
true
true
true
[四娃, 大娃, 二娃, 三娃, 金刚葫芦娃, 五娃]
四娃
大娃
五娃
[二娃, 三娃, 金刚葫芦娃]
-----------------华丽的分割线------------------
二娃
三娃
金刚葫芦娃
二娃
三娃
金刚葫芦娃
3.5 知识点: 自己思考下
- 自己思考并总结,ArrayList和LinkedList区别: