Collection集合体系(ArrayList,LinekdList,HashSet,LinkedHashSet,TreeSet,Collections)

目录

一.Collection

二.List集合

三.ArrayList集合

四.LinkedList集合

五.Set集合

六.hashSet集合

七.LinkedHashSet集合

八.TreeSet集合

九.集合工具类Collections


集合体系概述

单列集合:Collection代表单列集合,每个元素(数据)只包含一个值。

双列集合:Map代表双列集合,每个元素包含两个值(键值对)。

单列集合:

List系列集合:添加的元素是有序、可重复、有索引

ArrayList:有序、可重复、有索引

LinekdList:有序、可重复、有索引

Set系列集合:添加的元素是无序、不重复、无索引

HashSet:无序、不重复、无索引

LinkedHashSet:有序、不重复、无索引

TreeSet:按照大小默认升序排序、不重复、无索引

一.Collection

为什么要先学Collection的常用方法?

Collection是单列集合的祖宗,它规定的方法(功能)是全部单列集合都会继承的。

Collection的常用方法:

代码展示:

java 复制代码
package com.itheima.day06.teacher.g_collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;

/**
 * Collection常用方法
 */
public class CollectionDemo {

    public static void main(String[] args) {
        /*
          Collection 是 ArrayList祖宗
         */
//        Collection<String> con = new ArrayList<>();//多态
//        ArrayList<String> list = new ArrayList<>();//本态
        //采用多态?为什么呢?  多态特点  多态下只能调用 父中定义的功能,不会调用子类特有的。
        // 我们要研究是 共性的功能 使用多态
        Collection<String> con = new ArrayList<>();//多态
        // add()
        con.add("name1");
        con.add("name2");
        con.add("name3");
        con.add("name4");
        System.out.println(con);
        //size() 获取集合长度 元素个数
        System.out.println("集合中有"+con.size()+"个元素");
        // boolean contains(元素)  判断集合中是否包含指定元素
        System.out.println("是否包含张三 "+con.contains("张三"));//false
        System.out.println("是否包含赵四 "+con.contains("赵四"));//true
        //boolean remove(元素)  删除指定元素 返回 是否删除成功
        System.out.println("删除一下:王老七 "+con.remove("王老七"));
        System.out.println(con);
        //情况集合方法 void clear()
        con.clear();
        System.out.println("清空集合之后:"+con);
        // isEmpty() 判断集合是否为空
        System.out.println("con当前是空的吗?"+con.isEmpty());
        // 重写添加数据
        con.add("谢大脚");
        con.add("王小蒙");
        con.add("香秀");
        con.add("王云");
        // Object[] toArray() 变成数组
        Object[] array = con.toArray();
        System.out.println(Arrays.toString(array));
        //扩展一个


        Collection<String> c1 = new ArrayList<>();//多态
        // add()
        c1.add("name1");
        c1.add("name2");
        c1.add("name3");
        c1.add("name4");

        Collection<String> c2 = new ArrayList<>();//多态
        // add()
        c2.add("name1");
        c2.add("name2");
        c2.add("name3");
        c2.add("name4");

        c1.addAll(c2);//c2集合内容 批量添加到c1中
        System.out.println(c1);
    }
}

Collection的遍历方式:

1.迭代器:

迭代器是用来遍历集合的专用方式(数组没有迭代器),在Java中迭代器的代表是Iterator。

Collection集合获取迭代器的方法 Iterator<E> iterator() 返回集合中的迭代器对象,该迭代器对象默认指向当前集合的第一个元素

Iterator迭代器中的常用方法:

boolean hasNext():询问当前位置是否有元素存在,存在返回true ,不存在返回false

E next():获取当前位置的元素,并同时将迭代器对象指向下一个元素处。

2.增强for循环:

格式:for (元素的数据类型 变量名 : 数组或者集合) { }

增强for可以用来遍历集合或者数组。

增强for遍历集合,本质就是迭代器遍历集合的简化写法。

3.lambda表达式

得益于JDK 8开始的新技术Lambda表达式,出现了一种更简单、更直接遍历集合的方式-Lambda表达式。

需要使用Collection的如下方法来完成:default void forEach(Consumer<? super T> action)

lists.forEach(s -> {System.out.println(s); });

java 复制代码
package com.itheima.day06.teacher.g_collection;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo2 {

    public static void main(String[] args) {
        /*
          Collection 是 ArrayList祖宗
         */
//        Collection<String> con = new ArrayList<>();//多态
//        ArrayList<String> list = new ArrayList<>();//本态
        //采用多态?为什么呢?  多态特点  多态下只能调用 父中定义的功能,不会调用子类特有的。
        // 我们要研究是 共性的功能 使用多态
        Collection<String> con = new ArrayList<>();//多态
        // add()
        con.add("name1");
        con.add("name2");
        con.add("name3");
        con.add("name4");
        System.out.println(con);
        //size() 获取集合长度 元素个数
//        for (int i = 0; i < con.size(); i++) {
//           String s =  con.get(i);//Conllection 认为无索引
//        }
        // Collection集合的遍历 需要借助一个工具 来完成遍历(迭代)
                                  //  迭代器 Interator
        // 每一个集合对象 都有自己的 迭代器。
        // 呼叫迭代器 获取迭代器
        Iterator<String> it = con.iterator();
        // iterator 可以帮助集合完成 元素的获取
        // 迭代器指向第一个元素

        while(it.hasNext()){//询问 当前位置是否有元素 有true false
            //再去获取
            String e = it.next();
            System.out.println(e);

        }


    }
}

-------------

package com.itheima.day06.teacher.g_collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;

public class CollectionDemo3 {

    public static void main(String[] args) {
        /*
          Collection 是 ArrayList祖宗
         */
//        Collection<String> con = new ArrayList<>();//多态
//        ArrayList<String> list = new ArrayList<>();//本态
        //采用多态?为什么呢?  多态特点  多态下只能调用 父中定义的功能,不会调用子类特有的。
        // 我们要研究是 共性的功能 使用多态
        Collection<String> con = new ArrayList<>();//多态
        // add()
        con.add("name1");
        con.add("name2");
        con.add("name3");
        con.add("name4");
        System.out.println(con);

         //因为开发中 大量场景都要使用到 集合 都要去完成遍历 所以jdk 升级的时候 做了一个很高明的操作 就是简化迭代器的使用
        /*
           增强for - --单列集合  数组

           for(数据类型 变量名 :被遍历的集合/数组){}

         */
//        for(String s:con){
//            System.out.println(s);
//        }
        //集合.for
        for (String s : con) {
            System.out.println(s);
        }
        //增强for 只适合于获取数据 不适合与修改

    }
}


----------

package com.itheima.day06.teacher.g_collection;

import java.util.ArrayList;
import java.util.Collection;
import java.util.function.Consumer;

public class CollectionDemo4 {

    public static void main(String[] args) {
        /*
          Collection 是 ArrayList祖宗
         */
//        Collection<String> con = new ArrayList<>();//多态
//        ArrayList<String> list = new ArrayList<>();//本态
        //采用多态?为什么呢?  多态特点  多态下只能调用 父中定义的功能,不会调用子类特有的。
        // 我们要研究是 共性的功能 使用多态
        Collection<String> con = new ArrayList<>();//多态
        // add()
        con.add("name1");
        con.add("name2");
        con.add("name3");
        con.add("name4");
        System.out.println(con);

       /*
         jdk8提供的 foreach
        */
        con.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {//s 接收每次得到的数据
                System.out.println(s);
            }
        });
        System.out.println("=================");
        con.forEach(s -> System.out.println(s));

        con.forEach(System.out::println);
    }
}

二.List集合

1.List集合因为支持索引,所以多了很多与索引相关的方法

特有方法:

2.遍历方式:

1.for循环(因为List集合有索引)

2.迭代器

3.增强for循环

4.Lambda表达式

java 复制代码
package com.itheima.day07.teacher.list01;

import java.util.ArrayList;
import java.util.List;

public class ListDemo {
    /*
     Collection 单列集合顶层接口
        里面定义关于元素的  一些 获取添加删除的通用方法
       --- List 子接口  有序集合
          特点:
             有序  可以重复  有索引
             里面 有写特有和索引相关方法
          增  void add(int index,E e) 往集合指定位置添加元素
          删  E remove(int index) 根据指定索引进行删除  返回被删除元素
          改  E set(int index,E e) 根据索引进行元素替换,返回被替换的元素
          查  E get(int index) 根据索引获取元素

     */
    public static void main(String[] args) {
        // 这是多态写法 因为在多态下只能使用List 接口定义的方法
        List<String> list = new ArrayList<>();
        //添加元素
        list.add("name1");
        list.add("name2");
        list.add("name3");
        list.add("name4");
        System.out.println(list);
        //有序--存取顺序一致。且有索引
        // 索引为3的位置添加一个 真玲
        list.add(3,"真玲");
        System.out.println(list);
        // 删除
        // 删除索引为4的元素
        String remove = list.remove(4);
        System.out.println("删除索引为4的元素:"+remove);
        System.out.println("删除后的集合:"+list);
//        System.out.println(list.remove(4)); 报错  索引越界
        //修改  索引为2的 改为狗蛋
        System.out.println(list.set(2,"狗蛋"));
        System.out.println("修改后的集合:"+list);
        // 获取  索引为1的元素
        System.out.println(list.get(1));



    }
}


-----------
package com.itheima.day07.teacher.list01;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class ListDemo02 {

    public static void main(String[] args) {
        /*
        完成集合的遍历
           遍历方式 四种
         */
        List<String> list  =  new ArrayList<>();
        list.add("name1");
        list.add("name2");
        list.add("name3");
        list.add("name4");

        //普通for循环  list集合.fori
        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }
        System.out.println("===============");
        //迭代器 iterator()
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }
        System.out.println("===============");
        //增强for  list集合.for
        for (String s : list) {
            System.out.println(s);
        }
        // lambda 集合.forEach
        list.forEach(s -> System.out.println(s));
        System.out.println("===============");
        list.forEach(System.out::println);
    }
}

三.ArrayList集合

1.ArrayList集合底层是基于数组实现的

2.数组的特点:查询快,增删慢(数组长度固定,增删需要新数组效率低)

3.ArrayList集合对象的创建和扩容过程

1、利用无参构造器创建的集合,会在底层创建一个默认长度为0的数组

2、添加第一个元素时,底层会创建一个新的长度为10的数组

3、存满时,会扩容1.5倍

4、如果一次添加多个元素,1.5倍还放不下,则新创建数组的长度以实际为准

4.ArrayList集合适合什么业务场景?不适合什么业务场景?

适合根据索引查询数据的场景或者数据量不是很大的场景

不适合数据量很大时又要频繁地进行增删操作的场景

因为比较常用我单独写了一篇

**四.**LinkedList集合

1.LinkedList集合底层是基于双链表实现的

2.链表中的结点是独立的对象,在内存中是不连续的,每个结点包含数据值和下一个结点的地址。

3.链表的特点:查询慢,都要从头开始找,增删快

4.双链表的特点:

每个节点包含数据值和上一个节点的地址以及下一个节点的地址

查询慢,增删相对较快,但对首尾元素进行增删改查的速度是极快的

5.LinkedList新增了:很多首尾操作的特有方法。

6.LinkedList集合适合需要频繁操作首尾元素的场景,比如栈和队列

java 复制代码
package com.itheima.day07.teacher.list02;

import java.util.LinkedList;

public class LikendListDemo01 {

    public static void main(String[] args) {
        /*
          用LinkedList模拟 小火车过山洞...模拟 队列结构

           队列结构
              先进先出 FIFO

         */
        LinkedList<String> list = new LinkedList<>();
        //入队 进山洞
        list.addLast("火车头");
        list.addLast("第一节车厢");
        list.addLast("第二节车厢");
        list.addLast("第三节车厢");
        list.addLast("火车尾");

        //出山洞
        System.out.println(list.removeFirst());
        System.out.println(list.removeFirst());
        System.out.println(list.removeFirst());
        System.out.println(list.removeFirst());
        System.out.println(list.removeFirst());


    }
}


------------

package com.itheima.day07.teacher.list02;

import java.util.LinkedList;

public class LinkedListDemo02 {

    public static void main(String[] args) {
        /*
         模拟弹夹  发射子弹
             栈结构
               特点 先进后出 FILO
         */
        LinkedList<String> danJia = new LinkedList<>();

        // 压 子弹
        danJia.addFirst("第一颗子弹");//每次都在最上面
        danJia.addFirst("第二颗子弹");//每次都在最上面
        danJia.addFirst("第三颗子弹");//每次都在最上面
        danJia.addFirst("第四颗子弹");//每次都在最上面

        // 射子弹
        System.out.println(danJia.removeFirst());//每次射最上面的
        System.out.println(danJia.removeFirst());
        System.out.println(danJia.removeFirst());
        System.out.println(danJia.removeFirst());
    }
}

五.Set集合

整体特点: 无序 ,存取顺序不保证一致; 不重复; 无索引;

HashSet: 无序、不重复、无索引

LinkedHashSet:有序、不重复、无索引

TreeSet:可排序、不重复、无索引

六.hashSet集合

1.哈希值:

1.就是一个int类型的数值,Java中每个对象都有一个哈希值

2.Java中的所有对象,都可以调用Obejct类提供的hashCode方法,返回该对象自己的哈希值

2.对象哈希值的特点:

同一个对象多次调用hashCode()方法返回的哈希值是相同的。

不同的对象,它们的哈希值一般不相同,但也有可能会相同(哈希碰撞)。

3.HashSet底层基于哈希表实现

JDK8之前,哈希表 = 数组+链表

1.创建一个默认长度16的数组,默认加载因子为0.75,数组名table

2.使用元素的哈希值对数组的长度求余计算出应存入的位置

3.判断当前位置是否为null,如果是null直接存入

4.如果不为null,表示有元素,则调用equals方法比较

JDK8开始,哈希表 = 数组+链表+红黑树(一种平衡的二叉树)

JDK8开始,当链表长度超过8,且数组长度>=64时,自动将链表转成红黑树

JDK8开始后,哈希表中引入了红黑树后,进一步提高了操作数据的性能。

哈希表是一种增删改查数据性能都较好的结构。

4.数据结构:树

二叉查找树:规则:小的往左存,大的往右存,一样的不存

可能存在的问题:当数据已经是排好序的,导致查询的性能与单链表一样,查询速度变慢!

**平衡二叉树:**在满足二叉查找树的大小规则下,让树尽可能矮小,以此提高查数据的性能。

**红黑树:**是一种可以自平衡的二叉树,红黑树是一种增删改查数据性能相对都较好的结构

5.如何让HashSet集合能够实现对内容一样的两个不同对象也能去重复?

重写hashCode()和equals()方法

java 复制代码
package com.itheima.day07.teacher.set02;

import java.util.Objects;

/**
 * 学术类
 */
public class Student {
    private String name;
    private int age;
    private double height;


    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return height
     */
    public double getHeight() {
        return height;
    }

    /**
     * 设置
     * @param height
     */
    public void setHeight(double height) {
        this.height = height;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", height = " + height + "}";
    }

    //利用idea快捷键  hashCode equals

    /*
      比较两个对象的内容
     */
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age && Double.compare(student.height, height) == 0 && Objects.equals(name, student.name);
    }
    /*
     根据属性算哈希值  尽量不一样的属性 值不同 减少哈希碰撞
     */
    @Override
    public int hashCode() {
        return Objects.hash(name, age, height);
    }
}


------------
package com.itheima.day07.teacher.set02;

import java.util.HashSet;

public class HashSetDemo {

    public static void main(String[] args) {
        /*
          创建一个学生集合  用来存储不同 学生对象
         */
        HashSet<Student> set = new HashSet<>();
        //创建学生对象
        Student stu1 = new Student("小磊",18,1.88);
        Student stu2 = new Student("小鑫",28,1.38);
        Student stu3 = new Student("小哲",22,1.78);
        Student stu4 = new Student("小鑫",28,1.38);

        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu2);
        set.add(stu4);//我们没有重写 hashCode equals的时候可以存储进去的,
            // 原因是 存的时候先调用 hashCode方法(Object--根地址有一定关系) 哈希code不一样.
            // 即使哈希一样,也能存!!没有重写equals 比较的是地址值  不是一个元素。
        /*
           在开发过程中
               是地址值不一样就是不同对象吗?
               其实不尽然,我们开发中认为 两个对象如果 所有属性值都一样 认为是 同一个对象。
               在我们观点里面 stu2 stu4是同一个对象。
               默认情况下没有当成 同一个对象 并没有完成 元素的去重
         如果 想要达到开发标准 两个对象属性值都一样 就是同一个对象怎么做?
            重写
               hashCode()  -- 目的  是要根据内容算哈希值。
               equals()    -- 目的  是进行内容比较。
            重写之后
              stu2 stu4 先算出哈希值 哈希碰撞  位置一样 再进行equals比较 内容一样不存
         */


        for (Student student : set) {
            System.out.println(student);
        }
        /*
         存储元素原理
             先根据hashcode算出 存储位置
             位置上有元素 就进行equals比较。

         */
    }
}

**七.**LinkedHashSet集合

依然是基于哈希表(数组、链表、红黑树)实现的

但是,它的每个元素都额外的多了一个双链表的机制记录它前后元素的位置

八.TreeSet集合

  1. 特点:不重复、无索引、可排序(默认升序排序 ,按照元素的大小,由小到大排序)

对于数值类型:Integer , Double,默认按照数值本身的大小进行升序排序。

对于字符串类型:默认按照首字符的编号升序排序。

2.底层是基于红黑树实现的排序

3.TreeSet集合中对自定义类型元素排序方案:

方式一:让自定义的类(如学生类)实现Comparable接口,重写里面的compareTo方法来指定比较规则。

方式二:通过调用TreeSet集合有参数构造器,可以设置Comparator对象(比较器对象,用于指定比较规则)

java 复制代码
package com.itheima.day07.teacher.set03;

/**
    学生类
*/

public class Student implements Comparable<Student> {
    private String name;
    private int age;
    private double height;


    public Student() {
    }

    public Student(String name, int age, double height) {
        this.name = name;
        this.age = age;
        this.height = height;
    }

    /**
     * 获取
     * @return name
     */
    public String getName() {
        return name;
    }

    /**
     * 设置
     * @param name
     */
    public void setName(String name) {
        this.name = name;
    }

    /**
     * 获取
     * @return age
     */
    public int getAge() {
        return age;
    }

    /**
     * 设置
     * @param age
     */
    public void setAge(int age) {
        this.age = age;
    }

    /**
     * 获取
     * @return height
     */
    public double getHeight() {
        return height;
    }

    /**
     * 设置
     * @param height
     */
    public void setHeight(double height) {
        this.height = height;
    }

    public String toString() {
        return "Student{name = " + name + ", age = " + age + ", height = " + height + "}";
    }


    @Override
    public int compareTo(Student o) {
        return this.age-o.age;//前-后 升序
    }
}


-------------
package com.itheima.day07.teacher.set03;


import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo {
    /*
      TreeSet
        底层是一个 二叉排序树
           遵循特点
             小的存左边 大的存右边 一样的不存
        里面的存储的元素必须具备 !!排序功能!! 元素之间有大小关系
     */
    public static void main(String[] args) {

        TreeSet<Integer> set1 = new TreeSet<>();
        set1.add(13);
        set1.add(15);
        set1.add(12);
        set1.add(33);
        set1.add(26);
        set1.add(13);
        set1.add(14);

        System.out.println(set1);
        /*
          TreeSet去重原则  一样的不存
          存完之后元素进行排序
            是因为 存储的元素类型有排序规则
               implements Comparable<Integer>
               实现 Comparable 代表有了排序的规则 所以可以使用TreeSet存储
            TreeSet 去重的原理
                是排序的规则 如果一样就不存。
         */

        System.out.println("==========");
       TreeSet<String>  set2 = new TreeSet<>();
       set2.add("cba");
       set2.add("cbb");
       set2.add("aba");
       set2.add("bbb");
       set2.add("cbb");
       System.out.println(set2);

    }
}


-------------
package com.itheima.day07.teacher.set03;


import java.util.Comparator;
import java.util.TreeSet;

public class TreeSetDemo01 {

    /*
      开发中不建议 用TreeSet存储自定义类型,因为会根据只定义排序内容进行去重,与实际开发不符。
        如果执意要用 你就得对所有的 属性进行排序比较 规则

      如果要用TreeSet存自定义类型
         1:自定义类型 实现 Comparable接口  实现排序规则。
         2:在 TreeSet 构造中 写出临时的排序规则 传递规则Comparator接口。

     */
    public static void main(String[] args) {

        //创建学生对象
       Student stu1 = new Student("小磊",18,1.88);
       Student stu2 = new Student("小鑫",28,1.38);
       Student stu3 = new Student("小哲",22,1.78);
       Student stu4 = new Student("小迪",28,1.68);
      //创建 TreeSet集合
       TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
           @Override
           public int compare(Student o1, Student o2) {
               return o2.getAge()-o1.getAge();//按照年龄降序
           }
       });
        //存元素
        set.add(stu1);
        set.add(stu2);
        set.add(stu3);
        set.add(stu4);

        for (Student student : set) {
            System.out.println(student);
        }

    }
}

Collection集合使用小结:

1、如果希望记住元素的添加顺序,需要存储重复的元素,又要频繁的根据索引查询数据?

用ArrayList集合(有序、可重复、有索引),底层基于数组的。(常用)

2、如果希望记住元素的添加顺序,且增删首尾数据的情况较多?

用LinkedList集合(有序、可重复、有索引),底层基于双链表实现的。

3.如果不在意元素顺序,也没有重复元素需要存储,只希望增删改查都快?

用HashSet集合(无序,不重复,无索引),底层基于哈希表实现的。(常用)

4.如果希望记住元素的添加顺序,也没有重复元素需要存储,且希望增删改查都快?

用LinkedHashSet集合(有序,不重复,无索引),底层基于哈希表和双链表,

5.如果要对元素进行排序,也没有重复元素需要存储?且希望增删改查都快?

用Treeset集合,基于红黑树实现。

集合的并发修改异常:

使用迭代器遍历集合时,又同时在删除集合中的数据,程序就会出现并发修改异常的错误"王麻子");("小李子");由于增强for循环遍历集合就是迭代器遍历集合的简化写法,因此,使用增强for循环遍历("李爱花");在同时("张全蛋");("晓李");删除集合中的数据时,程序也会出现并发修改异常的错误。("李玉刚");

怎么保证遍历集合同时删除数据时不出bug?

使用迭代器遍历集合,但用迭代器自己的删除方法删除数据即可

如果能用for循环遍历时:可以倒着遍历并删除;或者从前往后遍历,但删除元素后做i--操作

九.集合工具类Collections

Collections代表集合工具类,提供的都是静态方法,用来操作集合元素的。

常用静态方法:

public static <T> void sort(List<T> list):

数值型的List集合,按照值特性排序,默认升序

字符串的List集合,按照字符串元素的首字母编号排序。默认升序

对于自定义类型的集合,List<Student> ,默认报错的解决方法

解决方式一:让学生类实现比较规则Comparable接口。重写比较方法。

解决方式二:可以让sort方法自带一个比较器

java 复制代码
package com.itheima.day07.teacher.other;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

public class EditException {
   /*
     并发修改异常
        什么是并发修改异常:
             ConcurrentModificationException
             在使用迭代器(增强for) 遍历元素的同时,通过集合对象删除了集合中的指定数据,
             这个时候就会出现并发修改异常。
        原因是什么:
           迭代器里面 元素个数  和 集合中元素个数不一致了。
        怎么避免并发修改异常:
           在开发中不在迭代器 迭代过程中 使用集合删除对象。

           使用迭代器去删 迭代器删除的同时会给集合进行同步。
    */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("name1");
        list.add("name2");
        list.add("name3");
        list.add("name3");
        list.add("name4");
        list.add("name5");
        System.out.println(list); // [王麻子, 小李子, 李爱花, 张全蛋, 晓李, 李玉刚]

//需求:找出集合中带"李"字的姓名,并从集合中删除
        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            String name = it.next();
            if(name.contains("李")){
//                list.remove(name);不用集合删  用迭代器删除
                it.remove();//迭代器删除 会同步给集合
            }
        }
        System.out.println(list);
    }
}


-------------
package com.itheima.day07.teacher.other;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

public class CollenctionsDemo {
    /*
        集合工具类使用
     */
    public static void main(String[] args) {
        //ArrayList集合 是Collection子类 也是List子类
        List<String> list = new ArrayList<>();
        //
//        list.add("a");  一个一个元素添加
        //批量添加 Collections.addAll(Collection集合,T...t)//T 泛型的意思 集合里面是什么类型 泛型就是什么类型
        Collections.addAll(list,"nba","cba","qba","abc");

        System.out.println("查看集合内容:"+list);
        // 打乱顺序方法   --针对有序集合的(List)
        // Collections.shuffle(List集合)
        Collections.shuffle(list);
        System.out.println("打乱后集合内容:"+list);
        // 对集合元素排序 --针对有序集合(List)
        // Collections.sort(List集合)  有前提 元素类型 具备排序规则 需要实现Comparable接口
        Collections.sort(list); //按照默认顺序 升序
        System.out.println("排序之后:"+list);
        // 临时改变排序规则
        //  Collections.sort(List集合,Comparator接口实现类对象) 按照当前自己定义的排序规则排序
        Collections.sort(list, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o2.compareTo(o1);//字符串进行 降序  后面比较前面
            }
        });
        System.out.println("自定义排序规则后:"+list);
    }
}
相关推荐
跃ZHD2 分钟前
前后端分离,Jackson,Long精度丢失
java
blammmp23 分钟前
Java:数据结构-枚举
java·开发语言·数据结构
何曾参静谧36 分钟前
「C/C++」C/C++ 指针篇 之 指针运算
c语言·开发语言·c++
暗黑起源喵42 分钟前
设计模式-工厂设计模式
java·开发语言·设计模式
WaaTong1 小时前
Java反射
java·开发语言·反射
Troc_wangpeng1 小时前
R language 关于二维平面直角坐标系的制作
开发语言·机器学习
努力的家伙是不讨厌的1 小时前
解析json导出csv或者直接入库
开发语言·python·json
Envyᥫᩣ1 小时前
C#语言:从入门到精通
开发语言·c#
九圣残炎1 小时前
【从零开始的LeetCode-算法】1456. 定长子串中元音的最大数目
java·算法·leetcode
wclass-zhengge1 小时前
Netty篇(入门编程)
java·linux·服务器