Java 入门35 List系列集合, 几黑的并发修改异常问题 LinkedList
![](https://img2022.cnblogs.com/blog/1805814/202206/1805814-20220629222147327-1934862216.png)
![](https://img2022.cnblogs.com/blog/1805814/202206/1805814-20220629222203464-1215831866.png)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ITheima.Collection; import java.util.ArrayList; /** 目标:ArrayList集合。 Collection集合的体系 Collection<E>(接口) / \ Set<E>(接口) List<E>(接口) / \ / \ \ HashSet<E>(实现类) TreeSet<E>(实现类) LinkedList<E>(实现类) Vector(线程安全) ArrayList<E>(实现类) / LinkedHashSet<E>(实现类) Collection集合体系的特点: Set系列集合: 添加的元素,是无序,不重复,无索引的。 -- HashSet:添加的元素,是无序,不重复,无索引的。 -- LinkedHashSet:添加的元素,是有序,不重复,无索引的。 List系列集合:添加的元素,是有序,可重复,有索引的。 -- LinkedList: 添加的元素,是有序,可重复,有索引的。 -- ArrayList: 添加的元素,是有序,可重复,有索引的。 -- Vector 是线程安全的,速度慢,工作中很少使用。 1、List集合继承了Collection集合的全部功能,"同时因为List系列集合有索引", 2、因为List集合多了索引,所以多了很多按照索引操作元素的功能: 3、ArrayList实现类集合底层基于数组存储数据的,查询快,增删慢! - public void add(int index, E element): 将指定的元素,添加到该集合中的指定位置上。 - public E get(int index):返回集合中指定位置的元素。 - public E remove(int index): 移除列表中指定位置的元素, 返回的是被移除的元素。 - public E set(int index, E element):用指定元素替换集合中指定位置的元素,返回更新前的元素值。 小结: ArrayList集合的底层是基于数组存储数据。查询快,增删慢!(相对的) */ public class Test5 { public static void main(String[] args) { //1 创建一个ArrayList集合对象 //List:有序,可重复 有索引 ArrayList<String> list=new ArrayList<>(); list.add("HTML"); list.add("CSS"); list.add("JS"); list.add("Python"); list.add("Java"); list.add("MySql"); //2 在某个索引出插入元素 list.add(2,"白马"); System.out.println(list);//[HTML, CSS, 白马, JS, Python, Java, MySql] //3 更具索引删除元素,返回被删除元素 System.out.println(list.remove(2));//白马 System.out.println(list);//[HTML, CSS, JS, Python, Java, MySql] //4 更具索引获取是元素: public E get(){int index ,E element}; list.set(1,"船只教育"); System.out.println(list);//[HTML, 船只教育, JS, Python, Java, MySql] } }
![](https://img2022.cnblogs.com/blog/1805814/202206/1805814-20220629223259150-1762761912.png)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ITheima.Collection; import java.util.ArrayList; import java.util.Iterator; import java.util.List; /** * 拓展:List系列集合的遍历方式有:4种。 * <p> * List系列集合多了索引,所以多了一种按照索引遍历集合的for循环。 * <p> * List遍历方式: * (1)for循环。(独有的,因为List有索引)。 * (2)迭代器。 * (3)foreach。 * (4)JDK 1.8新技术。 */ public class Test6 { 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 (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("---------------------------------------"); //lists.for+回车键 for (String list : lists) { System.out.println(list); } //4 JDK 1.8之后的Lambda表达式 System.out.println("---------------------------------------"); //简写 lists.forEach(s -> { System.out.println(s); }); System.out.println("---------------------------------------"); } }
ArrayList集合的底层实现原理
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.itheima.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、做一个队列: LinkedList<String> queue = new LinkedList<>(); // 入队 queue.addLast("1号"); queue.addLast("2号"); queue.addLast("3号"); System.out.println(queue); // 出队 // System.out.println(queue.getFirst()); System.out.println(queue.removeFirst()); System.out.println(queue.removeFirst()); System.out.println(queue); // 2、做一个栈 LinkedList<String> stack = new LinkedList<>(); // 入栈 压栈 (push) stack.push("第1颗子弹"); stack.push("第2颗子弹"); stack.push("第3颗子弹"); stack.push("第4颗子弹"); System.out.println(stack); // 出栈 弹栈 pop System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack.pop()); System.out.println(stack); } }
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
package com.ITheima.Collection; import java.util.ArrayList; import java.util.Iterator; /** * 目标:研究集合遍历并删除元素可能出现的:并发修改异常问题。 */ public class Test7 { public static void main(String[] args) { // 1、准备数据 ArrayList<String> list = new ArrayList<>(); list.add("黑马"); list.add("Java"); list.add("Java"); list.add("赵敏"); list.add("赵敏"); list.add("素素"); System.out.println(list); // [黑马, Java, Java, 赵敏, 赵敏, 素素] // 需求:删除全部的Java信息。 // a、迭代器遍历删除 Iterator<String> it = list.iterator(); while (it.hasNext()) { String ele = it.next(); if ("Java".equals(ele)) { //list.remove("Java");会漏删 it.remove();//使用迭代器删除当前所在元素,并且不会后移 } } //b forEach遍历删除(会出现bug) /* for (String s : list) { if("Java".equals(s)){ //list.remove("Java");会漏删 有bug } }*/ //c lambda 表达式 会漏删 有bug /*list.forEach(s->{ if("Java".equals(s)){ list.remove("Java");//会漏删 有bug } });*/ // c、lambda表达式(会出现问题,这种无法解决的,Lambda遍历不能边遍历边删除,会出bug) // list.forEach(s -> { // if("Java".equals(s)){ // list.remove(s); // } // }); // d、for循环(边遍历边删除集合没毛病,但是必须从后面开始遍历删除才不会出现漏掉应该删除的元素) for (int i = list.size() - 1; i >= 0; i--) { String ele = list.get(i); if ("Java".equals(ele)) { list.remove(ele); } } System.out.println(list); } }