一、集合框架

1、什么是集合框架

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

主要表现为把多个元素(element)放在一个单元中,用于对这些元素进行快速、便捷的存储(store)、检索(retrieve)、管理(manipulate),即平时俗称的增删改查(CRUD)

类和接口总览

2、背后涉及的数据结构以及算法

2.1什么是数据结构

数据结构(Data Structure)是计算机存储、组织数据的方式,指互相之间存在一种或多种特定关系的数据元素的集合

2.2容器背后对应的数据结构

(1)Collection:一个接口,包含了大部分容器常用的一些方法

(2)List:一个接口,规范了ArrayList和LinkedList中要实现的方法

                        ArrayList:实现了List接口,底层为动态类型顺序表

                        LinkedList:实现了List接口,底层为双向链表

(3)Stack:底层是栈,栈是一种特殊的顺序表

(4)Queue:底层是队列,队列是一种特殊的顺序表

(5)Deque:是一个接口

(6)Set:集合,是一个接口,里面放置的是K模型

                        HashSet:底层为哈希桶,查询的时间复杂度为O(1)

                        TreeSet:底层为红黑树,查询的时间复杂度为O( logN ),关于key有序的

(7)Map:映射,里面存储的是K-V模型的键值对

HashMap:底层为哈希桶,查询时间复杂度为O(1)

TreeMap:底层为红黑树,查询的时间复杂度为O(logN),关于key有序

2.3什么是算法

算法(Algorithm):就是定义良好的计算过程,他取一个或一组的值为输入,并产生出一个或一组值作为输出。简单来说算法就是一系列的计算步骤,用来将输入数据转化成输出结果。

二、时间和空间复杂度

1、算法效率

算法效率分析分为两种:第一种是时间效率,第二种是空间效率。时间效率被称为时间复杂度,而空间效率被称作空间复杂度。时间复杂度主要衡量的是一个算法的运行速度,而空间复杂度主要衡量一个算法所需要的额外空间

(在计算机发展的早期,计算机的存储容量很小。所以对空间复杂度很是在乎。但是经过计算机行业的迅速发展,计 算机的存储容量已经达到了很高的程度。所以我们如今已经不需要再特别关注一个算法的空间复杂度。)

2、时间复杂度

2.1时间复杂度的概念

时间复杂度的定义:在计算机科学中,算法的时间复杂度是一个数学函数,它定量描述了该算法的运行时间。一个算法执行所耗费的时间,从理论上说,是不能算出来的,只有你把你的程序放在机器上跑起来,才能知道。但是我们需要每个算法都上机测试吗?是可以都上机测试,但是这很麻烦,所以才有了时间复杂度这个分析方式。一个算法所花费的时间与其中语句的执行次数成正比例,算法中的基本操作的执行次数,为算法的时间复杂度。

2.2大O的渐进表示法

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

也就是F(N) = N^2 + 2*N + 10

实际我们计算时间复杂度时,我们只需要算大概执行的次数,也就是大O的渐进表示法

大O符号(Big O notation):是用于描述函数渐进行为的数学符号。

2.3推导大O阶方法

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

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

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

使用大O的渐进表示法以后,Func1的时间复杂度为:O(N^2)

通过上面我们会发现大O的渐进表示法去掉了那些对结果影响不大的项,简洁明了的表示出了执行次数。 另外有些算法的时间复杂度存在最好、平均和最坏情况:

最坏情况:任意输入规模的最大运行次数(上界)(最慢)

平均情况:任意输入规模的期望运行次数

最好情况:任意输入规模的最小运行次数(下界)(最快)

2.4常见的时间复杂度计算举例

例一、

void func3(int N, int M) {int count = 0; for (int k = 0; k < M; k++) {count++;//M} for (int k = 0; k < N ; k++) {count++;//N} System.out.println(count);}

由于基本操作执行了N+M次,并且两数都是未知数,所以时间复杂度为O(N+M)

例二、

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;}//N*(N-1)/2} if (sorted == true) {break;}}}

由于循环执行,第一次执行(N-1)次,最后一次执行了0次,共N次,求每次比前一次少一次,因此得到N*(N-1)/2,因此时间复杂度为O(N^2)

例三、

int binarySearch(int[] array, int value) {int begin = 0;int end = array.length - 1;while (begin <= end) {int mid = begin + ((end-begin) / 2);if (array[mid] < value)begin = mid + 1;else if (array[mid] > value)end = mid - 1;elsereturn mid;}return -1;}

二分查找,一次是原来的一半可以得出(N/2)^O=1,计算可得时间复杂度为O(logN)(logN是以2为底,lgN是以10为底)

例四、

 long factorial(int N) {return N < 2 ? N : factorial(N-1) * N;}

阶乘递归是在比较N和2的大小关系进行选择,可以发现共递归了N次,所以时间复杂度为O(N)

例五、

 int fibonacci(int N) {return N < 2 ? N : fibonacci(N-1)+fibonacci(N-2);}

可以发现,左侧最顶端(第一次)是(N-1),最后一次是1,也就可以得到近似的1+2^1+……+2^(N-1),也就是2^N-1,同理,右侧也可以计算出是2^(N-1)-1,因此时间复杂度为O(2^N)

我们常遇到的复杂度有:O(1) < O(logN) < O(N) < O(N*logN) < O(N^2)

3、空间复杂度

空间复杂度是对一个算法在运行过程中临时占用存储空间大小的量度 。空间复杂度不是程序占用了多少bytes的空间,因为这个也没太大意义,所以空间复杂度算的是变量的个数。空间复杂度计算规则基本跟时间复杂度类似,也使用大O渐进表示法。

例一、

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)

例二、

 int[] fibonacci(int n) {long[] fibArray = new long[n + 1];fibArray[0] = 0;fibArray[1] = 1;for (int i = 2; i <= n ; i++) {fibArray[i] = fibArray[i - 1] + fibArray [i - 2];}return fibArray;}

因为动态开辟了N个空间,空间复杂度为 O(N)

例三、

 long factorial(int N) {return N < 2 ? N : factorial(N-1)*N;}

因为递归调用了N次,开辟了N个栈帧,每个栈帧使用了常数个空间,因此空间复杂度为O(N)

三、包装类&简单认识泛类

1、包装类

在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java给每个基本类型都对应了一个包装类型。

1.1基本数据类型和对应的包装类

1.2装箱和拆箱

 int i = 10; // 装箱操作,新建一个 Integer 类型对象,将 i 的值放入对象的某个属性中Integer ii = Integer.valueOf(i);Integer ij = new Integer(i);// 拆箱操作,将 Integer 对象中的值取出,放到一个基本数据类型中int j = ii.intValue();

1.3自动装箱和自动拆箱

我们可以看到在使用过程中,装箱和拆箱带来不少的代码量,所以为了减少开发者的负担,java 提供了自动机制。

int i = 10;Integer ii = i;              // 自动装箱
Integer ij = (Integer)i;     // 自动装箱int j = ii;                  // 自动拆箱
int k = (int)ii;             // 自动拆箱

2.泛型

实现一个类,类中包含一个数组成员,使得数组中可以存放任何类型的数据,也可以根据成员方法返回数组中某个下标的值?

思路:

(1)我们以前学过的数组,只能存放指定类型的元素,例如:int[] array = new int[10]; String[] strs = new String[10];

(2)所有类的父类,默认为Object类。数组是否可以创建为Object?

class MyArray {public Object[] array = new Object[10];public Object getPos(int pos) {return this.array[pos];}public void setVal(int pos,Object val) {this.array[pos] = val;}}public class TestDemo {public static void main(String[] args) {MyArray myArray = new MyArray();myArray.setVal(0,10);myArray.setVal(1,"hello");//字符串也可以存放String ret = myArray.getPos(1);//编译报错System.out.println(ret);}}

问题:以上代码实现后发现

(1)任何类型数据都可以存放

(2)1号下标本身就是字符串,但是却编译报错。必须进行强制类型转换

虽然在这种情况下,当前数组任何数据都可以存放,但是,更多情况下,我们还是希望他只能够持有一种数据类型。而不是同时持有这么多类型。所以,泛型的主要目的:就是指定当前的容器,要持有什么类型的对象。让编译 器去做检查。此时,就需要把类型,作为参数传递。需要什么类型,就传入什么类型。

2.1语法

class 泛型类名称<类型形参列表> {// 这里可以使用类型参数
}class ClassName<T1, T2, ..., Tn> {  
}
class 泛型类名称<类型形参列表> extends 继承类/* 这里可以使用类型参数 */ {// 这里可以使用类型参数
}class ClassName<T1, T2, ..., Tn> extends ParentClass<T1> {// 可以只使用部分类型参数
}

上述代码进行改写如下:

class MyArray<T> {public Object[] array =  new Object[10];public T getPos(int pos) {return (T)this.array[pos];}public void setVal(int pos,T val) {this.array[pos] = val;}}public class TestDemo {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();//1myArray.setVal(0,10);myArray.setVal(1,12);int ret = myArray.getPos(1);//2System.out.println(ret);myArray.setVal(2,"bit");//3}}

代码解释:

(1)类名后的代表占位符,表示当前类是一个泛型类

(了解: 【规范】类型形参一般使用一个大写字母表示,常用的名称有:

E 表示 Element

K 表示 Key

V 表示 Value

N 表示 Number

T 表示 Type

S, U, V 等等 - 第二、第三、第四个类型)

(2)注释1处,类型后加入指定当前类型

(3)注释2处,不需要进行强制类型转换

(4)注释3处,代码编译报错,此时因为在注释2处指定类当前的类型,此时在注释3处,编译器会在存放元素的时候帮助我们进行类型检查。

3、泛型的使用

3.1语法

泛型类<类型实参> 变量名;  // 定义一个泛型类引用
new 泛型类<类型实参>(构造方法实参);  // 实例化一个泛型类对象

例:

MyArray<Integer> list = new MyArray<Integer>();

#注:泛型只能接受类,所有的基本数据类型必须使用包装类!

3.2 类型推导(Type Inference)

当编译器可以根据上下文推导出类型实参时,可以省略类型实参的填写

MyArray<Integer> list = new MyArray<>(); // 可以推导出实例化需要的类型实参为 Integer

4、擦除机制

在编译的过程当中,将所有的T替换为Object这种机制,我们称为:擦除机制。

Java的泛型机制是在编译级别实现的。编译器生成的字节码在运行期间并不包含泛型的类型信息。

编译完成以后,T被擦除为Object(编译期间用T进行类型的检查和转换)

5、泛型的上界

在定义泛型类时,有时需要对传入的类型变量做一定的约束,可以通过类型边界来约束。

5.1语法

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

例:

 public class MyArray<E extends Number> {...}

只接受 Number 的子类型作为 E 的类型实参

MyArray<Integer> l1;        // 正常,因为 Integer 是 Number 的子类型
MyArray<String>  l2;        // 编译错误,因为 String 不是 Number 的子类型

(当没有指定的边界时,可以认为E extends Object)

6、泛型方法

6.1定义语法

方法限定符 <类型形参列表> 返回值类型 方法名称(形参列表) { ... }

例:

 public class Util {//静态的泛型方法 需要在static后用<>声明泛型类型参数public static <E> void swap(E[] array, int i, int j) {E t = array[i];array[i] = array[j];array[j] = t;}}

四、List的介绍

1、什么是List

在集合框架中,List是一个接口,继承自Collection。

Collection也是一个接口(继承自Iterable),该接口中规范了后序容器中常用的一些方法,具体如下所示:

Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下:

站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作。

在这里我们先简单的认识一下List就可以了,后续内容会补充介绍,这里只需要简单的看一下有什么就可以了(List太多,有兴趣的话可以去自己看一下)

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebStack-Hugo | 一个静态响应式导航主题

WebStack-Hugo | 一个静态响应式导航主题 #10 shenweiyan announced in 1.3-折腾 WebStack-Hugo | 一个静态响应式导航主题#10 ​编辑shenweiyan on Oct 23, 2023 6 comments 7 replies Return to top shenweiyan on Oct 23, 2023 Maintainer Via&#xff1a;我给自己…

01 基于sklearn的机械学习-机械学习的分类、sklearn的安装、sklearn数据集、数据集的划分、特征工程中特征提取与无量纲化

文章目录机械学习机械学习分类1. 监督学习2. 半监督学习3. 无监督学习4. 强化学习机械学习的项目开发步骤scikit-learn1 scikit-learn安装2 sklearn数据集1. sklearn 玩具数据集鸢尾花数据集糖尿病数据集葡萄酒数据集2. sklearn现实世界数据集20 新闻组数据集3. 数据集的划分特…

携全双工语音通话大模型亮相WAIC,Soul重塑人机互动新范式

近日&#xff0c;WAIC 2025在上海隆重开幕。作为全球人工智能领域的顶级盛会&#xff0c;本届WAIC展览聚焦底层能力的演进与具体垂类场景的融合落地。坚持“模应一体”方向、立足“AI社交”的具体场景&#xff0c;Soul App此次携最新升级的自研端到端全双工语音通话大模型亮相&…

第2章 cmd命令基础:常用基础命令(1)

Hi~ 我是李小咖&#xff0c;主要从事网络安全技术开发和研究。 本文取自《李小咖网安技术库》&#xff0c;欢迎一起交流学习&#x1fae1;&#xff1a;https://imbyter.com 本节介绍的命令有目录操作&#xff08;cd&#xff09;、清屏操作&#xff08;cls&#xff09;、设置颜色…

Java 10 新特性解析

Java 10 新特性解析 文章目录Java 10 新特性解析1. 引言2. 本地变量类型推断&#xff08;JEP 286&#xff09;2.1. 概述2.2. 使用场景2.3. 限制2.4. 与之前版本的对比2.5. 风格指南2.6. 示例代码2.7. 优点与注意事项3. 应用程序类数据共享&#xff08;JEP 310&#xff09;3.1. …

【WRF工具】服务器中安装编译GrADS

目录 安装编译 GrADS 所需的依赖库 conda下载库包 安装编译 GrADS 编译前检查依赖可用性 安装编译 GrADS 参考 安装编译 GrADS 所需的依赖库 以统一方式在 $HOME/WRFDA_LIBS/grads_deps 下安装所有依赖: # 选择一个目录用于安装所有依赖库 export DIR=$HOME/WRFDA_LIBS库包1…

数据结构之队列(C语言)

1.队列的定义&#xff1a; 队列&#xff08;Queue&#xff09;是一种基础且重要的线性数据结构&#xff0c;遵循先进先出&#xff08;FIFO&#xff09;​​ 原则&#xff0c;即最早入队的元素最先出队&#xff0c;与栈不同的是出队列的顺序是固定的。队列具有以下特点&#xff…

C#开发基础之深入理解“集合遍历时不可修改”的异常背后的设计

前言 欢迎关注【dotnet研习社】&#xff0c;今天我们聊聊一个基础问题“集合已修改&#xff1a;可能无法执行枚举操作”背后的设计。 在日常 C# 开发中&#xff0c;我们常常会操作集合&#xff08;如 List<T>、Dictionary<K,V> 等&#xff09;。一个新手开发者极…

【工具】图床完全指南:从选择到搭建的全方位解决方案

前言 在数字化内容创作的时代&#xff0c;图片已经成为博客、文档、社交媒体等平台不可或缺的元素。然而&#xff0c;如何高效、稳定地存储和分发图片资源&#xff0c;一直是内容创作者面临的重要问题。图床&#xff08;Image Hosting&#xff09;作为专门的图片存储和分发服务…

深度学习篇---PaddleDetection模型选择

PaddleDetection 是百度飞桨推出的目标检测开发套件&#xff0c;提供了丰富的模型库和工具链&#xff0c;覆盖从轻量级移动端到高性能服务器的全场景需求。以下是核心模型分类、适用场景及大小选择建议&#xff08;通俗易懂版&#xff09;&#xff1a;一、主流模型分类及适用场…

cmseasy靶机密码爆破通关教程

靶场安装1.首先我们需要下载一个cms靶场CmsEasy_7.6.3.2_UTF-8_20200422,下载后解压在phpstudy_pro的网站根目录下。2.然后我们去访问一下安装好的网站&#xff0c;然后注册和链接数据库3.不知道自己数据库密码的可以去小皮面板里面查看4.安装好后就可以了来到后台就可以了。练…

【C语言】指针深度剖析(一)

文章目录一、内存和地址1.1 内存的基本概念1.2 编址的原理二、指针变量和地址2.1 取地址操作符&#xff08;&&#xff09;2.2 指针变量和解引用操作符&#xff08;*&#xff09;2.2.1 指针变量2.2.2 指针类型的解读2.2.3 解引用操作符2.3 指针变量的大小三、指针变量类型的…

半导体企业选用的跨网文件交换系统到底应该具备什么功能?

在半导体行业的数字化转型过程中&#xff0c;跨网文件交换已成为连接研发、生产、供应链的关键纽带。半导体企业的跨网文件交换不仅涉及设计图纸、工艺参数等核心知识产权&#xff0c;还需要满足跨国协同、合规审计等复杂需求。那么&#xff0c;一款适合半导体行业的跨网文件交…

影刀RPA_初级课程_玩转影刀自动化_网页操作自动化

声明&#xff1a;相关内容来自影刀学院&#xff0c;本文章为自用笔记&#xff0c;切勿商用&#xff01;&#xff08;若有侵权&#xff0c;请联络删除&#xff09; 1. 基本概念与操作 1.1 正确处理下拉框元素&#xff08;先判断页面元素&#xff0c;后进行流程编制&#xff09;…

Spark初探:揭秘速度优势与生态融合实践

更多推荐阅读 Spark与Flink深度对比&#xff1a;大数据流批一体框架的技术选型指南-CSDN博客 LightProxy使用操作手册-CSDN博客 Sentry一看就会教程_sentry教程-CSDN博客 微前端架构解析&#xff1a;核心概念与主流方案特性对比_微前端方案对比-CSDN博客 目录 Spark为何比Hadoo…

详谈OSI七层模型和TCP/IP四层模型以及tcp与udp为什么是4层,http与https为什么是7层

一、网络模型&#xff1a;OSI七层 vs TCP/IP四层OSI七层模型 (理论参考模型):目的&#xff1a;提供一个标准化的理论框架&#xff0c;用于理解网络通信过程和各层的功能划分&#xff0c;促进不同厂商设备的互操作性。它是一个理想化的模型。分层 (从下到上):物理层&#xff1a;…

ClickHouse 高性能实时分析数据库-索引与数据跳过(查询的“瞬移”能力)

告别等待&#xff0c;秒级响应&#xff01;这不只是教程&#xff0c;这是你驾驭PB级数据的超能力&#xff01;我的ClickHouse视频课&#xff0c;凝练十年实战精华&#xff0c;从入门到精通&#xff0c;从单机到集群。点开它&#xff0c;让数据处理速度快到飞起&#xff0c;让你…

Jetpack - Room(Room 引入、Room 优化)

一、Room 引入 1、基本介绍 Room 在 SQLite 上提供了一个抽象层&#xff0c;以便在充分利用 SQLite 的强大功能的同时&#xff0c;能够流畅地访问数据库&#xff0c;官方强烈建议使用 Room 而不是 SQLite 2、演示 &#xff08;1&#xff09;Setting 模块级 build.gradle depend…

【江科大CAN】2.1 STM32 CAN外设(上)

2.1 STM32 CAN外设&#xff08;上&#xff09;2.1.1 STM32 CAN外设简介2.1.2 外围电路设计2.1.3 STM32 CAN内部结构2.1.4 发送流程详解2.1.5 接收流程详解2.1.6 关键配置位总结STM32 CAN外设讲解 大家好&#xff0c;欢迎继续观看CAN总线入门教程。本节开始&#xff0c;我们正式…

人工智能技术革命:AI工具与大模型如何重塑开发者工作模式与行业格局

引言&#xff1a;AI技术爆发的时代背景过去五年间&#xff0c;人工智能领域经历了前所未有的爆发式增长。从2020年GPT-3的横空出世到2023年多模态大模型的全面突破&#xff0c;AI技术已经从实验室走向了产业应用的前沿。开发者作为技术生态的核心推动者&#xff0c;其工作模式正…