Java 第十一天(纯干货)(Collection 、ArrayList 、List集合、迭代器、增强for)(带你14天了解并掌握Java SE)

今日内容

  • 集合的概述和Collection集合
  • List集合
  • 数据结构和ArrayList集合的相关案例

01. 为什么会出现集合类

  • 1. 集合的特点
  • 2. 为什么要有集合
总结:
    1. 相同点: 集合和数组都是容器, 用来存储数据的

       不同点:
                数组存储:可以存储基本数据类型, 也可以存储引用数据类型
                        存储基本数据类型的时候, 存储的是值              int[] arr = {11,22,33};
                                                                    Person p1 = new Perosn();  Person p2 = new Person();
                        存储引用数据类型的时候, 存储的是地址值            Person[] pArr = new Person[2];
                                                                    pArr[0] = p1;   pArr[1] = p2;


                集合存储: 只能存储引用数据类型


                长度: 数组的长度是固定的, 集合的长度可变的.

    2. 举例:
            学生管理系统, 记录学生的各项信息

                    如果使用数组进行存储, 数组长度初始为80个大小, 这时候插班进来的第81个学生就没有位置存储了.   

                    问题产生: 使用数组就不合适了

                        解决方案: 使用一个长度可变的容器, [集合]

02. 集合类体系结构图

  • 再画一张

03. 创建Collection集合对象并添加元素

  • 为什么要先学习Collection?
  • 创建集合对象的时候, <>代表什么?
总结:
    1. Collection是单列集合的根接口, 内部定义的规则, 所有实现类都会具备一份


    /*
     * 细节1: 如果一个类没有找到我们使用的方法, 可以去父类中查询
     * 
     * 问题: 接口到底有没有继承Object类
     * 
     *  细节2: 接口没有继承Object类, 但是接口底层会有Object类所有方法的引用
     * 
     * 目的: 就是为了方式多态调用方法的编译报错!
     */
    2. <> : 泛型(jdk1.5新特性) -> 用于限制集合中存储的数据类型

            集合存储: 只能存储引用数据类型, 是因为泛型的特点, <>中只能编写引用数据类型


代码:
    public class Demo1_Collection {
        public static void main(String[] args) {
            // 1. 创建集合对象
            // 在jdk1.7版本之后, 右侧的尖括号中可以不写类型, 菱形泛型
            // <> : 泛型 -> 用于限制集合中存储的数据类型
            Collection<String> c = new ArrayList<>();
            // 2. 向集合中添加元素
            c.add("abc");
            c.add("bbb");
            // 3. 展示集合中的元素
            System.out.println(c.toString());
        }
    }

04. Collection集合的成员方法

  • boolean add(E e):添加元素
  • boolean remove(Object o):从集合中移除元素 ***
  • void clear():清空集合中的元素
  • boolean contains(Object o):判断集合中是否存在指定的元素 ***
  • boolean isEmpty():判断集合是否为空
  • int size():集合的长度,也就是集合中元素的个数

    示例代码:

    public static void main(String[] args) {
        // 1. 创建集合对象, 容器中存储的是Person对象
        Collection<Person> c = new ArrayList<>();
        // 2. 向集合中添加Person对象.
        c.add(new Person("张三", 23)); 
        c.add(new Person("李四", 24));
        c.add(new Person("王五", 25));
    
        // 注意: 如果添加的元素是自定义对象的话, 那么没有重写toString, 将打印地址值
        System.out.println(c);
    
        // 3. 调用集合的删除方法, 删除张三
        // 注意 : remove方法底层依赖于equals方法.
        c.remove(new Person("张三", 23));
        System.out.println(c);
    
        // 4. 调用集合中判断是否包含的方法
        // 注意 : contains方法底层依赖于equals方法.
        System.out.println(c.contains(new Person("李四", 24)));
    
        // 5. 调用集合的清空方法
        c.clear();
        // 6. 调用集合判断是否为空的方法
        System.out.println(c.isEmpty());
        // 7. 打印集合的长度
        System.out.println(c.size());
    }
    

05. Collection集合的遍历

  • 使用迭代器遍历集合的步骤
总结:
    1. 调用集合的iterator方法, 获取迭代器
            Iterator<String> it = c.iterator();
    2. 使用循环判断集合中是否还有元素
            while(it.hasNext()){

            }
    3. 使用next方法元素取出
            while(it.hasNext()){
                String s = it.next();
            }


示例代码:

        public static void main(String[] args) {
            Collection<Person> c = new ArrayList<>();
            c.add(new Person("张三", 23)); 
            c.add(new Person("李四", 24));
            c.add(new Person("王五", 25));

            // 1. 获取迭代器对象
            Iterator<Person> it = c.iterator();
            // 2. 循环判断集合中是否还有元素
            while(it.hasNext()){
                // 3. 获取元素
                Person p = it.next();
                System.out.println(p);
            }
        }

06. 集合(迭代器)使用步骤图解

  • 看图说话

07. Collection集合的练习存储自定义对象并遍历

  • 需求: 定义一个标准的学生类, 创建三个学生对象存储到集合容器中, 并遍历集合.

  • 6分钟练习

08. List集合的特点

  • List集合有什么特点?
总结:
    1. 存取有序
    2. 有索引
    3. 可以存储重复的

09. List集合的特有成员方法

  • void add(int index, E element) :将元素添加到index索引位置上
  • E get(int index) :根据index索引获取元素
  • E remove(int index) :根据index索引删除元素
  • E set(int index, E element):将index索引位置的的元素设置为element

10. List集合的普通for循环遍历

  • 案例演示
public class Test2_List {
    /*
     * List集合特有的一种遍历方式
     *      1. get(int index) : 根据传入的索引, 获取指定位置的元素
     *      2. size() : 返回集合的长度
     */
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("abc1");
        list.add("abc2");
        list.add("abc3");
        list.add("abc4");

//      String s1 = list.get(0);
//      String s2 = list.get(1);
//      String s3 = list.get(2);
//      String s4 = list.get(3);

        for(int i = 0; i < list.size(); i++){
            System.out.println(list.get(i));
        }

    }
}

11. List集合的练习存储自定义对象并遍历

  • 需求: 定义一个标准的学生类, 创建三个学生对象存储到集合容器中, 并遍历集合.
    1. 普通for循环

    2. 普通迭代器

    3. ListIterator特有的迭代器 --> 基本使用和普通迭代器一致

        // 1. 获取列表迭代器
        ListIterator<Student> listIt = list.listIterator();
        // 2. 判断集合中是否还有元素
        while(listIt.hasNext()){
            // 3. 调用next获取元素
            System.out.println(listIt.next());
        }

12. 列表迭代器的特有功能(了解)

  • 方法摘要:
总结:
    1.boolean hasPrevious()  : 判断集合是否还有上一个元素
    2.E previous()          : 获取集合中的上一个元素.

注意: 特有的功能比较鸡肋
            倒序遍历之前, 必须有正序遍历的铺垫, 才能取出来元素


    List<Person> list = new ArrayList<>();
    list.add(new Person("张三", 23));
    list.add(new Person("李四", 24));
    list.add(new Person("王五", 25));

    // 1. 获取列表迭代器
    ListIterator<Person> it = list.listIterator();

    // 2. 循环判断是否还有元素
    while(it.hasNext()){
        // 3. 使用next方法获取元素
        System.out.println(it.next());
    }

    System.out.println("----------------------");


    while(it.hasPrevious()){
        System.out.println(it.previous());
    }
  • 5分钟时间练习

13. 并发修改异常产生的原因及解决方案(重点)

  • 什么情况下会产生并发修改异常?
  • 如何解决?
总结:
    1. 当使用迭代器在遍历集合的过程中, 使用集合的添加或删除方法操作元素
                就会产生并发修改异常

    2. 不让使用集合的添加或删除, 就使用迭代器自身的添加或删除

            删除: 普通迭代器中存在

            添加: 列表迭代器

扩展:
    如果用集合的remove方法删除的是倒数第二个元素的时候, 则不会报出并发修改异常(了解)

        原因: 略过了编译器的检查.      -> 少调用了一次checkxxxxx方法

14. 增强for(jdk1.5的新特性)的概述和使用

  • 增强for循环的格式是?
  • 增强for循环底层依赖于什么技术实现?
总结:
    1. 

        for(数据类型 变量名 : 要遍历的数组或集合){

        }

    2.

        增强for循环底层是迭代器实现的

            只要是能用迭代器遍历的容器, 都可以使用增强for循环改进.

            注意1: 增强for循环不能使用集合的删除方法, 会产生并发修改异常
            注意2: 增强for循环中, 不能删除元素

15. 增强for的练习List集合存储自定义对象并遍历

  • 案例演示
public static void main(String[] args) {
    List<Person> list = new ArrayList<>();
    list.add(new Person("张三", 23));
    list.add(new Person("李四", 24));
    list.add(new Person("王五", 25));

    for(Person p : list){
        System.out.println(p);
    }
}

16. 常见数据结构之栈和队列

  • 栈内存结构什么特点?
  • 队列内存结构什么特点?
总结:
    1: 桟内存结构,类似于手枪弹夹
            特点: 先进后出
    2: 队列内存结构, 类似于一条管道
            特点: 先进先出

17. 常见数据结构之数组和链表

  • 数组
    优点:查询快, 修改快

            原因: 因为数组有索引, 有索引的话, 就可以快速的定位到要操作的元素, 并快速的进行修改.

    缺点:增删慢

            原因: 因为每一次的添加或删除都需要大批量的操作数据中的元素

                    删除: 将数组中的元素删除之后, 后面的元素会整体的向前移动一位
                            假如数组长度为100, 我们将第一个元素进行删除, 后续的99个元素都要进行移动

                    增加: 以ArrayList为举例, 底层就是数组结构的, 假设底层数组长度为10个大小, 我们在添加第11个元素的时候
                            底层就会根据原数组, 自动扩容一个1.5倍大小的新数组, 再将数组内容拷贝一份到新数组中去, 随后再把第11个元素进行添加.
  • 链表
    优点: 增删快

                只需要将两个元素的引用切断, 然后重新规划引用即可, 不会影响到过多的元素.

                删除也是如此.

    缺点: 查询慢, 修改慢

                每一次查找元素, 都会在链表结构当中, 逐个的做元素检索.


                问题: 查询元素的时候从头开始查, 还是从尾开始查?

                        底层源码会进行一个判断, 如果离头近, 就从前往后找, 如果离尾近, 从后往前找.

                            问题: 如何进行的判断?

                                    会根据索引进行折半查找

                                    问题: LinkedList有索引吗?

                                            因为是List派系下的子类,所以存在索引, 但是查找的时候就是不用!

18. List集合子类特点及ArrayList集合存储字符串并遍历

  • ArrayList集合的特点, 完成什么样的功能较为合适?
总结:
    1.

        ArrayList<String> list = new ArrayList<>();

        list.add("abc");
        list.add("111");
        list.add("222");
        list.add("333");

        for (int i = 0; i < list.size(); i++) {
            System.out.println(list.get(i));
        }

        System.out.println("-------------");


        Iterator<String> it = list.iterator();
        while(it.hasNext()){
            System.out.println(it.next());
        }

        System.out.println("--------------------");

        for(String s : list){
            System.out.println(s);
        }

19. ArrayList集合的练习存储自定义对象并遍历

  • 回顾3种集合的迭代方式
    三种遍历是否能删除元素.
        1. 迭代器:  可以删除, 但是在调用remove方法之前必须调用next方法
                            问题: next方法会将指针向后移动一位, 为什么不需要--
                            答案: 底层自动帮我们实现了--的操作.
        2. 普通for : 可以删除, 但是索引需要--
        3. 增强for : 不能删, 因为会产生并发修改异常
  • 案例演示LinkedList集合的使用.
    public static void main(String[] args) {
        // 底层是链表结构
        LinkedList<String> list = new LinkedList<>();

        // 调用从Collection中继承下来的add方法添加元素
        list.add("1");
        list.add("2");
        list.add("3");

        // LinkedList特有的方法: 在头部添加元素
        list.addFirst("4");
        list.addFirst("5");

        // LinkedList特有的方法: 在尾部添加元素
        list.addLast("6");

        // LinkedList特有的方法: 删除第一个元素
        list.removeFirst();

        // LinkedList特有的方法: 删除最后一个元素
        list.removeLast();

        System.out.println(list);
    }
  • 问题: LinkedList集合底层是链表结构, 那么查询元素的时候从前开始找, 还是从后开始找?
    总结:
            1. 会查看要查找的元素, 离头近还是离尾近, 如果离头近, 就从头开始找, 反之, 就从尾开始找.
            2. LinkedList虽然是链表结构, 但是底层也有索引 !
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章