java数据结构前置知识以及认识泛型

news2025/1/19 22:18:29

目录

什么是集合框架

容器

时间复杂度

空间复杂度

包装类

装箱

拆箱

引出泛型

泛型类的使用

类型推导

泛型如何编译的

泛型的上界

泛型方法静态泛型方法以及泛型上界


什么是集合框架

Java 集合框架 Java Collection Framework ,又被称为容器 container ,是定义在 java.util 包下的一组接口 interfaces和其实现类 classes 。

如何理解这张图?

所有的这些从某种意义上说都实现了Iterable这个接口,然后collection继承extends了它也可以说拓展了它这个接口相当于collection这个接口具备了Iterable这个接口的功能,相当于这个接口定义的类型可以引用下面具体的对象,例如List list=new ArrayList()暂且这样写,后面同样一个道理

这张图描述了java当中 类与类 类与接口之间的关系

说明:java的集合类和关系不一定只有上图,上图只是描述了部分重要的常见的类


容器

每个容器其实都是对某种特定数据结构的封装

1. Collection 是一个接口,包含了大部分容器常用的一些方法
2. List 是一个接口,规范了 ArrayList LinkedList 中要实现的方法
ArrayList 实现了 List 接口,底层为动态类型顺序表
LinkedList :实现了 List 接口,底层为双向链表
3. Stack :底层是栈,栈是一种特殊的顺序表
4. Queue :底层是队列,队列是一种特殊的顺序表
5. Deque :是一个接口
6. Set :集合,是一个接口,里面放置的是 K 模型
HashSet :底层为哈希桶,查询的时间复杂度为 O(1)
TreeSet :底层为红黑树,查询的时间复杂度为 O(
), 关于 key 有序的
7. Map :映射,里面存储的是 K-V 模型的键值对
HashMap :底层为哈希桶,查询时间复杂度为 O(1)
TreeMap :底层为红黑树,查询的时间复杂度为 O(
) ,关于 key 有序


时间复杂度

时间效率被称为时间复杂度,算法中的基本操作的执行次数一般找执行语句最多的,为算法的时间复杂度

大O的渐进表示法:

用法例子:

// 请计算一下func1基本操作执行了多少次?
    void func1(int N){
    int count = 0;
    for (int i = 0; i < N ; i++) {
    for (int j = 0; j < N ; j++) {
    count++;
}
}
    for (int k = 0; k < 2 * N ; k++) {
    count++;
}
    int M = 10;
    while ((M--) > 0) {
    count++;
}
    System.out.println(count);
}

只需要大概执行次数,那么这里我们使用大O的渐进表示法

满足三点:

1、用常数1取代运行时间中的所有加法常数

2、在修改后的运行次数函数中,只保留最高阶项

3、如果最高阶项存在且不是1,则去除与这个项目相乘的常数。得到的结果就是大O阶

在实际中一般情况关注的是算法的最坏运行情况,所以数组中搜索数据时间复杂度为O(N)


空间复杂度

而空间效率被称作空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少 bytes 的空 间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也 使用大 O 渐进表示法。
用法例子:
/ 计算bubbleSort的空间复杂度?
void bubbleSort(int[] array) {
    for (int end = array.length; end > 0; end--) {
    boolean sorted = true;
    for (int i = 1; i < end; i++) {
    if (array[i - 1] > array[i]) {
    Swap(array, i - 1, i);
    sorted = false;
}
}
    if (sorted == true) {
    break;
}
}
}

注意

如果算法中使用了固定数量的额外变量或数组,不随输入规模的增加而变化,则空间复杂度是O(1)。

如果算法使用了和输入规模相关的额外空间,比如创建了一个大小与输入规模相等的数组来存储结果,那么空间复杂度通常是 O(N)。

对于递归算法,需要考虑递归调用所使用的栈空间。

每次递归调用都会占用一定的栈空间,因此递归算法的空间复杂度通常是 O(N) 或者 O(log N),取决于递归调用的深度


包装类

Java 中,由于基本类型不是继承自 Object ,为了在泛型代码中可以支持基本类型, Java 给每个基本类型都对应了 一个包装类型
基本数据类型 包装类
byte       Byte
short      Short
int        Integer
long       Long
float      Float
double     Double
char       Character
boolean    Boolean

装箱

public static void main1(String[] args) {
        //装箱/装包:把一个 基本数据类型 转变为 包装类型
        Integer a = 10;// 隐式装箱/自动装箱
        int i = 99;
        Integer b = i;
        System.out.println(b);

        Integer aa = Integer.valueOf(10);//显示装箱
        System.out.println(aa);
    }
}

拆箱

  public static void main2(String[] args) {
        //拆箱/拆包:把一个 包装类型 转变为 基本数据类型
        Integer a = 66;
        int b = a;//自动拆箱
        System.out.println(b);

        int aa = a.intValue();//显示拆箱

        double d = a.doubleValue();//拆成double类型
    }


下列代码输出什么,为什么?
public class Test {
    public static void main(String[] args) {
        Integer a = 100;
        Integer b = 100;
        System.out.println(a == b);

        Integer a1 = 200;
        Integer b1 = 200;
        System.out.println(a1 == b1);

    }

解释如下:

Java 中的 Integer 类在范围为 [-128, 127] 内的整数上具有缓存功能,即当创建一个范围内的 Integer 对象时,会从缓存中获取已经存在的对象而不是新创建一个对象。这是因为在此范围内的整数被频繁使用,因此缓存可以提高性能和节省内存。

但是,当整数超出范围 [-128, 127] 时,每次创建的 Integer 对象都会是一个新的对象,因此这些对象的地址不同,即使它们的值相同。因此,对于超出范围的整数,使用 == 比较两个 Integer 对象时,结果通常会是 false。

结果:

a 和 b 的值都在范围内,因此它们的地址相同,a == b 返回 true。
c 和 d 的值超出范围,因此它们的地址不同,c == d 返回 false。


引出泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法
返回数组中某个 下标的值?
泛型语法例子:
/**
 * @param <T> 代表当前类 是一个 泛型类,<T>是一个占位符
 */
class MyArray<T> {
    //public T[] array = (T[]) new Object[10];
    public Object[] array = new Object[10];

    public void setValue(int pos, T val) {
        this.array[pos] = val;
    }

    public T getValue(int pos) {
        return (T) array[pos];//把返回类型 强转为指定类型
    }

}

public class Test2 {
    public static void main(String[] args) {
        //泛型其实就是将 类型 进行 传递
        MyArray<Integer> myArray = new MyArray<>();
        myArray.setValue(1, 10);
        System.out.println(myArray.getValue(1));

        MyArray<String> myArray1 = new MyArray<>();
        myArray1.setValue(0, "hello");
        System.out.println(myArray1.getValue(0));
    }
}
以上代码实现后 发现 任何类型数据都可以存放
1. 类名后的 <T> 代表占位符,表示当前类是一个泛型类
注意【规范】类型形参一般使用一个大写字母表示,常用的名称有:
2.不能new泛型类型的数组
虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类 型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型

泛型类的使用

例子:
MyArray<Integer> list = new MyArray<Integer>();
注意:泛型只能接受类,所有的基本数据类型必须使用包装类!
类型推导
例子:
MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer
小结:
1. 泛型是将数据类型参数化,进行传递
2. 使用 <T> 表示当前类是一个泛型类。
3. 泛型目前为止的优点:数据类型参数化,编译时自动进行类型检查和转换

泛型如何编译的

擦除机制

通过命令:javap -c 查看字节码文件,所有的T都是Object

在编译的过程当中,将所有的 T 替换为 Object 这种机制,我们称为: 擦除机制
Java 的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息

泛型的上界

语法:
class 泛型类名称<类型形参 extends 类型边界> {
...
}

例子:

public class MyArray<E extends Number> {
...
}
上述例子表示只接受 Number 的子类型作为 E 的类型实参
MyArray<Integer> l1; // 正常,因为 Integer 是 Number 的子类型
MyArray<String> l2; // 编译错误,因为 String 不是 Number 的子类型

泛型方法静态泛型方法以及泛型上界

定义语法:

方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }
例子:
class Person1 implements Comparable<Person1> {
    @Override
    public int compareTo(Person1 o) {
        return 0;
    }
}

//泛型类
//T一定是实现了Comparable这个接口
class A<T extends Comparable<T>> {//将来你指定这个A泛型类传入的类型参数一定是实现了Comparable这个接口

    public T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

//泛型方法
class B {
    public <T extends Comparable<T>> T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

//静态泛型方法
class B1 {
    public static <T extends Comparable<T>> T findMax(T[] array) {
        T max = array[0];
        for (int i = 1; i < array.length; i++) {
            if (max.compareTo(array[i]) < 0) {
                max = array[i];
            }
        }
        return max;
    }
}

public class Test4 {
    public static void main(String[] args) {
        //静态泛型方法
        Integer[] integers2 = {1, 2, 3, 4};
        Integer integer3 = B1.findMax(integers2);
        System.out.println(integer3);

        //泛型方法
        B b = new B();
        Integer[] integers1 = {1, 2, 3, 4};
        //类型推导:根据实参传值 来推导 此时的类型
        Integer integer1 = b.findMax(integers1);//两种写法
        Integer integer2 = b.<Integer>findMax(integers1);//两种写法,这个全一点,可以省略
        System.out.println(integer1);

        //泛型类
        A<Integer> a = new A<>();
        Integer[] integers = {1, 2, 3, 4};
        Integer integer = a.findMax(integers);
        System.out.println(integer);

        A<Person1> a1 = new A<>();
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1447274.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习12-基本感知器

感知器(Perceptron)是一种最简单的人工神经网络结构,由美国心理学家Frank Rosenblatt在1957年提出。它是一种单层的前馈神经网络,通常用于二分类问题。 基本感知器由多个输入节点、一个输出节点和一组权重参数组成。每个输入节点都与输出节点连接,并且具有一个对应的权重参…

html的格式化标签和图片(img)标签

格式化标签 加粗: strong标签和b标签倾斜: em标签和i标签删除线: del标签和s标签下划线: ins标签和u标签 <strong>stong 加粗</strong><b>b 加粗</b><em>倾斜</em><i>倾斜</i><del>删除线</del><s>删除线…

Linux操作系统基础(十三):Linux安装、卸载MySQL

文章目录 Linux安装、卸载MySQL 一、卸载系统自带的mariadb-lib 二、上传安装包并解压 三、按顺序安装 错误1: 错误2: 错误3: 错误4: 四、初始化数据库 五、目录授权&#xff0c;否则启动失败 六、启动msyql服务 七、查看msyql服务的状态 八、在/var/log/mysqld.l…

C语言—基础数据类型(含进制转换)

进制转换不多&#xff0c;但我觉得适合小白(我爱夸自己嘿嘿) 练习 1. 确认基础类型所占用的内存空间(提示&#xff1a;使用sizeof 运算符)&#xff1a; 在这里我说一下&#xff0c;long 类型通常占用 4 字节。在 64 位系统上&#xff0c;long 类型通常也可为 8 字节。 格式…

Windows搭建docker+k8s

安装Docker Desktop 从官网下载&#xff0c;然后直接安装即可&#xff0c;过程很简单&#xff0c;一直Next就行。 有一点需要注意就是要看好对应的版本&#xff0c;因为后边涉及到版本的问题。 https://www.docker.com/products/docker-desktop 安装完成&#xff0c;双击图…

C++,stl,map/multimap详解

目录 1.map的构造和赋值 2.map的大小和交换 3.map的插入和删除 4.map的查找和统计 5.map的排序 1.map的构造和赋值 #include<bits/stdc.h> using namespace std;void print(map<int,int> &mp) {for(map<int,int>::iterator it mp.begin(); it ! m…

泛型(Java)

一、定义 定义类、接口、方法时&#xff0c;同时声明了一个或者多个类型变量&#xff0c;成为泛型类、泛型接口、泛型方法&#xff0c;统称为泛型。 如下需要的结果类型是String&#xff0c;实际的是obj&#xff0c;那么我们来看看强制类型转换以后会发生什么&#xff1a; 报…

深入了解JavaScript混淆工具:jsjiami.v6

JavaScript混淆工具在前端开发中发挥着重要的作用&#xff0c;帮助开发者保护源代码&#xff0c;减少代码被轻易破解的风险。其中&#xff0c;jsjiami.v6 是一款备受开发者关注的混淆工具之一。本文将深入介绍jsjiami.v6的基本原理和使用方法&#xff0c;并通过案例代码演示其效…

《A++ 敏捷开发》- 8 获取高层支持

我&#xff1a;对过程改进来说&#xff0c;最重要的成功要素是什么&#xff1f; 客户&#xff1a;最难的是如何得到高层的支持&#xff0c;这不仅仅是嘴巴说说而已&#xff0c;而是要切实地给人、给时间。高层往往不清楚什么是质量改进的重点&#xff0c;但他们对员工的人均收入…

【Web】CVE-2021-31805 s2-062漏洞复现学习

目录 Struts2介绍 漏洞概况 OGNL与Struts2 简单原理 漏洞复现 正向rce 反弹shell payload分析 Struts2介绍 Struts 2 是一个流行的用于构建 Java Web 应用程序的开源 Web 应用程序框架。它是 Apache 软件基金会下的一个顶级项目&#xff0c;是 Struts 框架的升级版本。…

29.方法引用

方法引用 1. 概述2.引用静态方法2.1 概述2.2 代码示例 3. 引用成员方法3.1 概述3.2 分类3.2.1 其他类3.2.2 本类3.2.3 父类 3.3 代码示例 4. 引用构造方法4.1 概述4.2 代码示例 5. 使用类名引用成员方法5.1 概述5.2 代码示例 6. 引用数组的构造方法6.1 概述6.2 代码示例 7. 注意…

【Vue】computed与watch

&#x1f4dd;个人主页&#xff1a;五敷有你 &#x1f525;系列专栏&#xff1a;Vue⛺️稳重求进&#xff0c;晒太阳 计算属性 概念&#xff1a;基于现有的数据&#xff0c;计算出来新的属性&#xff0c;依赖的数据变化&#xff0c;自动重新计算 语法&#xff1a; 声明…

蓝牙BLE学习-安全

1.基本概念 蓝牙标准规定了5种基本的安全服务 身份验证:根据通信设备的蓝牙地址验证其身份。蓝牙不提供本地用户身份验证。保密性:确保只有授权的设备才能访问和查看传输的数据&#xff0c;防止窃听造成的信息泄露。授权(Authorization):在允许设备使用某项服务之前&#xff…

Vue-自定义属性和插槽(五)

目录 自定义指令 基本语法 (全局&局部注册) 指令的值 练习&#xff1a;v-loading 指令封装 总结&#xff1a; 插槽&#xff08;slot&#xff09; 默认插槽 插槽 - 后备内容&#xff08;默认值&#xff09; 具名插槽 具名插槽基本语法: 具名插槽简化语法: 作…

可视化工具:将多种数据格式转化为交互式图形展示的利器

引言 在数据驱动的时代&#xff0c;数据的分析和理解对于决策过程至关重要。然而&#xff0c;不同的数据格式和结构使得数据的解读变得复杂和困难。为了解决这个问题&#xff0c;一种强大的可视化工具应运而生。这个工具具有将多种数据格式&#xff08;包括JSON、YAML、XML、C…

调用讯飞火星AI大模型WebAPI

调用讯飞火星AI大模型 记录一次调用讯飞AI大模型的过程 官方文档 首先&#xff0c;去官网申请资格&#xff0c;获得必要秘钥等 再编写url&#xff0c;该url存在编码要求&#xff0c;具体看官网url编写 具体代码如下&#xff1a; getWebsocketUrl() {return new Promise((resol…

格式化字符串的简单学习

文章目录 Format String格式化字符串函数格式化字符串参数原理 这几天学的少&#xff0c;过完年就一直在走亲戚&#xff08;现在看到肉就犯恶心 Format String 格式化字符串函数可以接受可变数量的参数&#xff0c;并将第一个参数作为格式化字符串&#xff0c;根据其来解析之…

ChatGPT高效提问—prompt实践(视频制作)

ChatGPT高效提问—prompt实践&#xff08;视频制作&#xff09; 1.1 视频制作 ​ 制作视频对于什么都不懂的小白来说非常难。而随着AI技术的发展&#xff0c;这件事变得越来越简单&#xff0c;如今小白也可以轻松上手。如何借助ChatGPT来制作短视频。 ​ 其实方法非常简单&a…

【排序】归并排序

归并排序 动图演示&#xff1a; 基本思想&#xff1a;分治思想 归并排序&#xff08;MERGE-SORT&#xff09;是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。将已有序的子序列合并&#xff0c;得到完全有序的序列&#xff1b;即先使每个子…

CSS 评分器星星效果

<template><view class="rating"><!-- 5颗星 --><input value="5" name="rating" id="star5" type="radio"><label for="star5"></label><!-- 4颗星 --><input val…