Java 入门35 List系列集合, 几黑的并发修改异常问题 LinkedList

 

 

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]
    }
}
View Code
 
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("---------------------------------------");
    }

}
View Code

ArrayList集合的底层实现原理

 

 

 

 

 

 

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);

    }
}
View Code

 

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);
    }
}
View Code

 

posted @ 2022-06-29 22:22  还有什么值得拥有  阅读(51)  评论(0编辑  收藏  举报