Day05、集合概述——泛型

Day5、集合概述——泛型

前言:

1 、数组和集合的元素存储的个数问题。

. 数组定义后类型确定, 长度固定

. 集合类型可以不固定, 大小是可变的。

2 、数组和集合存储元素的类型问题。

. 数组可以存储基本类型和引用类型的数据。

. 集合只能存储引用数据类型的数据。

3 、数组和集合适合的场景

. 数组适合做数据个数和类型确定的场景(arraylist)

. 集合适合做数据个数不确定, 且要做增删元素的场景(collection)

Collection集合的体系特点

集合类体系结构:Collection(单列)+ Map(双列)

Collection单列集合,每个元素(数据)包含一个值

Map双列集合,每个元素包含两个之(键值对)

Collection集合体系

image-20220428210853562

Error:Cannot determine path to 'tools.jar' library for openjdk-18 (E:/JDK18)
    //运行时报错  IDEA版本和jdk版本不兼容
public class CollectionDemo01 {
    public static void main(String[] args) {
        //list系列集合 有序、可重复、有索引
        Collection list = new ArrayList();
        list.add("java");
        list.add("java");
        list.add("Mybatis");
        list.add(233);
        list.add(23);
        list.add(false);
        list.add(false);
        System.out.println(list);

        //set系列集合 无序、不重复、无索引
        Collection list1 = new HashSet();
        list1.add("java");
        list1.add("java");
        list1.add("Mybatis");
        list1.add(233);
        list1.add(23);
        list1.add(false);
        list1.add(false);
        System.out.println(list1);
    }
}

集合对于泛型的支持

. 集合都是支持泛型的, 可以在编译阶段约束集合只能操作某种数据类型

Collection<String> lists = new ArrayList<Stirng>();
Collection<String> lists = new ArrayList<>();//JDK1.7开始后面的泛型类型声明可以省略不写

注意: 集合和泛型都只能支持引用数据类型.不支持基本数据类型所以集合中存储的元素都认为是对象。

Collection<int> lists = new ArrayList<>();

如果集合中要存储基本类型的数据怎么办?

/ / 存储基本类型伊包类
Collection<Integer> lists = new ArrayList<>();
Collection<Doub1e> lists = new ArrayList<>();

集合的代表是?

. Collection 接囗。

Collection 集合分了哪2 大常用的集合体系?

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

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

如何约定集合存储数据的类型, 需要注意什么?

. 集合支持泛型。

. 集合和泛型不支持基本类型, 只支持引用数据类型。

Collection集合常用API

Collection集合

Collection集合是单列集合的祖宗接口,它的全部单列集合都是可以继承使用的

方法名称 说明
public boolean add(E e) 把给定的对象添加到当前集合中
public void clear() 清空集合中所有的元素
public boolean remove(E e) 把给定的对象在当前集合中删除
public boolean contains(Object obj) 判断当前集合中是否包含给定的对象
public boolean isEmpty() 判断当前集合是否为空
public int size() 返回集合中元素的个数。
public Object[] toArray() 把集合中的元素, 存储到数组中

Collection集合的遍历方式

迭代器遍历概述

. 遍历就是一个一个的把容器中的元素访问一遍。

. 迭代器在Java 中的代表是lterator, 迭代器是集合的专用遍历方式。

collection集合获取迭代器

方法名称 说明
Iterator iterator() 返回集合中的迭代器对象, 该迭代器对象默认指向当前集合的0索引

Iterator 中的常用方法

方法名称 说明
boolean hasNext() 询问当前位置是否有元素存在, 存在返回true , 不存在返回false
E next() 获取当前位置的元素, 并同时将迭代器对象移向下一个位置, 注意防止取出越界。
越界会出现NoSuchElementException异常。

增强for循环:

增强for 循环: 既可以遍历集合也可以遍历数组。

它是JDK5之后出现的, 其内部原理是一个terator 迭代器, 遍历集合相当于是迭代器的简化写法。

实现Iterable接口的类才可以使用迭代器和增强for,Collection 接口已经实现了Iterable接口。

格式

for ( 元素数据类型变量名: 数组或者Collection 集合) {

/ / 在此处使用变量即可, 该变量就是元素

}

ColIection<String> list = new ArrayList<>();
for(String ele : list) {
System.out.println(ele);
}
public class CollectionDemo02 {
    public static void main(String[] args) {
        Collection<String> c1 = new ArrayList<>();
        c1.add("灭绝");
        c1.add("芷若");
        c1.add("素素");
        c1.add("赵敏");
        System.out.println(c1);

        //1.增强for循环
        for (String ele : c1){
            System.out.println(ele);
        }

        double[] scores = {100,99,59.5};
        for (double s : scores) {
            System.out.println(s);
            /*if (s == 59.5){
                s = 100.1;
            }*/
             //修改无意义,不会影响数组的元素值
        }
        System.out.println(Arrays.toString(scores));


    }
}

Lambda表达式遍历集合

image-20220429195301376

Collection集合存储自定义类型的对象

image-20220429202124262

注意movie的位置,就是moive每一次移动一格位置,获取这个位置的元素,因为collection是接口,无法实现索引

集合中存储的是元素对象的地址

常见数据结构

数据结构概述:

  • 数据结构式计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。

  • 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率。

栈:后进先出,先进后出,类似于枪的弹夹-piapiapia

队列:先进先出,后进后出

  • 数据从后端进入队列模型的过程称为:入队列

  • 数据从前端离开队列模型的过程称为:出队列

数组:

  • 查询速度快: 查询数据通过地址值和索引定位, 查询任意数据耗时相同。( 元素在内存中是连续存储的)

  • 删除效率低: 要将原始数据删除, 同时后面每个数据前移。

  • 添加效率极低: 添加位置后的每个数据后移, 再添加元素。

链表:单向链表、双向链表

链表中的元素是内存中不连续存储的,每个元素节点包含数据值和下一个元素的地址。

链表查询慢

链表增删相对快

image-20220429203927981 image-20220501122917934

二叉树

image-20220501122954000 image-20220501123013340 image-20220501123028680

平衡二叉树:

  • 在满足查找二叉树的大小规则下,让树尽可能矮小,依次提高查数据的能力。

  • 要求任意节点的左右两个子树的高度差不超过1,任意节点的左右两个子树都是一颗平衡二叉树。

红黑树:

image-20220501123258291

红黑规则

image-20220501123340400 image-20220501123406602

各种数据结构的特点和作用是什么样的?

  • 队列: 先进先出, 后进后出。

  • 栈: 后进先出, 先进后出。

  • 数组: 内存连续区域, 查询快增删慢。

  • 链表: 元素是游离的, 查询慢, 首尾操作极快。

  • 二叉树: 永远只有一个根节点, 每个结点不超过2 个子节点的树。

  • 查找二叉树: 小的左边, 大的右边, 但是可能树很高, 查询性能变差。

  • 平衡查找二叉树: 让树的高度差不大于1 , 增删改查都提高了。

  • 红黑树( 就是基于红黑规则实现了自平衡的排序二叉树)

List系列集合

List集合特点、特有API

. ArrayList 、LinekdList : 有序, 可重复, 有索引。

. 有序: 存储和取出的元素顺序一致

. 有索引: 可以通过索引操作元素

. 可重复: 存储的元素可以重复

List集合特有方法

List集合因为支持索引,所以多了很多索引操作的独有API,其他collection的功能list也都继承了。

方法名称 说明
void add(int index, E element) 在此集合中的指定亻立置插入指定的元素
E remove(int index) 删除指定索引处的元素, 返回被删除的元素
E set(int index,E element) 修改指定索引处的元素, 返回被修改的元素
E get(int index) 返回指定索引处的元素
ublic class ListDemo01 {
    public static void main(String[] args) {
        //1.创建一个ArrauList集合对象
        //List:有序、可重复、有索引
        List<String> list = new ArrayList<>();
        list.add("java");
        list.add("java");
        list.add("MYSQL");
        list.add("MYSQL");
        //2.在某个索引位置插入元素
        list.add(2,"HTML");
        System.out.println(list);
        //3.根据索引删除元素,返回被删除元素
        System.out.println(list.remove(2));
        System.out.println(list);
        //4.根据索引获取元素:public E get(int index):返回集合中指定位置的元素。
        System.out.println(list.get(2));
        //5.修改索引位置处的元素:public E set(int index,E element)
        list.set(1,"高斯");
        System.out.println(list);
    }
}

List的实现类的底层原理:Arraylist都是基于数组实现的,根据查询元素快,增删相对慢;Linkedlist底层基于双链表实现的,查询元素慢,增删首尾元素是非常快的。

List集合的遍历方式小结:

  1. 迭代器

  2. 增强for循环

  3. Lambda表达式

  4. for循环(因为list集合存在索引)

Arraylist集合的底层原理

image-20220501131022562
ArrayList 底层是基于数组实现的: 根据索引定位元素快, 增删需要做元素的移位操作。
第一次创建集合并添加第一个元素的时候, 在底层创建一个默认长度为1 0 的数组。
new ArrayList<>();
List<String> list
list.add("a");
image-20220501132311797

LinkedList的特点

  • 底层数据结构是双链表,查询慢,首尾操作的速度是极快的,所以多了很多首尾操作的特有API

LinkedList集合的特有功能

方法名称 说明
public void addFirst(E e) 在该列表开头插入指定的元素
public void addLast(E e) 将指定的元素追加到此列表的末尾
public E getFirst() 返回此列表中的第一个元素
public E getLast() 返回此列表中的最后一个元素
public E removeFirst() 从此列表中删除并返回第一个元素
public E removeLast() 从此列表中删除并返回最后一个元素

链表的种类:

image-20220501134318413

拓展:集合的并发修改异常问题

问题引出

. 当我们从集合中找出某个元素并删除的时候可能出现一种并发修改异常问题。

哪些遍历存在问题?

. 迭代器遍历集合且直接用集合删除元素的时候可能出现。

. 增强for 循环遍历集合且直接用集合删除元素的时候可能出现。

哪种遍历且删除元素不出问题

  • 迭代器遍历集合但是用迭代器自己的删除方法操作可以解决的

  • 使用for循环遍历并删除元素不会存在这个问题。

补充知识:泛型深入

泛型概述:

. 泛型: 是JDK5 中引入的特性, 可以在编译阶段约束操作的数据类型, 并进行检查。

. 泛型的格式: < 数据类型> ; 注意: 泛型只能支持引用数据类型。

. 集合体系的全部接口和实现类都是支持泛型的使用的。

泛型的好处:

统一数据类型。

把运行时期的问题提前到了编译期间, 避免了强制类型转换可能出现的异常, 因为编译阶段类型就能定下来。

泛型可以再很多地方进行定义:

image-20220501142736936

自定义泛型类:

. 定义类时同时定义了泛型的类就是泛型类。

. 泛型类的格式: 修饰符class 类名< 泛型变量>

范例: public class MyArrayList<T> { }

. 此处泛型变量T 可以随便写为任意标识, 常见的如E 、T 、

. 作用: 编译阶段可以指定数据类型, 类似于集合的作用。

课程案例导学

. 模拟ArrayList 集合自定义一个集合MyArrayList 集合, 完成添加和删除功能的泛型设计即可。

泛型类的原理:

  • 把出现泛型变量的地方全部替换成传输的真实数据类型。

image-20220501144335688

泛型方法的概述

定义方法时同时定义了泛型的方法就是泛型方法。

泛型方法的格式: 修饰符< 泛型变量> 方法返回值方法名称( 形参列表)

范例: public <T> void show(T t) { }

作用: 方法中可以使用泛型接收一切实际类型的参数, 方法更具备通用性。

课程案例导学

给你任何一个类型的数组, 都能返回它的内容。也就是实Arrays.toString( 数组)的功能!

泛型方法的原理:

  • 把出现泛型变量的地方全部替换成传输的真实数据类型。

image-20220501145747702

image-20220501145854536

泛型接口的概述:

. 使用了泛型定义的接口就是泛型接口。

. 泛型接口的格式: 修饰符interface 接口名称< 泛型变量>

范例: public interface Data<E>{}

. 作用: 泛型接囗可以让实现类选择当前功能需要操作的数据类型

课程案例导学

. 教务系统, 提供一个接口可约束一定要完成数据( 学生, 老师) 的增删改查操作

泛型接囗的原理:

. 实现类可以在实现接口的时候传入自己操作的数据类型, 这样重写的方法都将是针对于该类型的操作。

泛型接口的作用:

  • 泛型接口可以约束实现类,实现类可以再实现接口的时候传入自己操作的数据类型这样重写的方法都将是针对于该类型的操作。

泛型通配符、上下限

通配符:就是?

  • ?可以在“使用泛型”的时候代表一切类型
  • ETKV实在定义泛型的时候使用的

上下限:

? extends Car : ?必须是Car或其子类 泛型上限
? super Car : ?必须是Car或其父类 泛型下限
posted on 2022-05-03 21:30  Cafune-Ding  阅读(134)  评论(0)    收藏  举报