.net core webapi 自定义异常过滤器

1.定义统一返回格式 namespace webapi; /// <summary> /// 统一数据响应格式 /// </summary> public class Results<T> { /// <summary> /// 自定义的响应码,可以和http响应码一致,也可以不一致 /// </summary> public int Code { get; set; } /// <summary> /// 中文消息提示 /// </summary> public string? Msg { get; set; } /// <summary> /// 是否成功 /// </summary> public bool Success { get; set; } /// <summary> /// 响应的数据 /// </summary> public T? Data { get; set; } /// <summary> /// 返回的Token: 如果有值,则前端需要此这个值替旧的token值 /// </summary> public string?

nvm下载node版本Could not retrieve https://nodejs.org/dist/latest/SHASUMS256.txt.Get “https://nodejs.o

1.使用nvm安装node版本的时候报错 Could not retrieve https://nodejs.org/dist/latest/SHASUMS256.txt. Get "https://nodejs.org/dist/latest/SHASUMS256.txt": dial tcp 104.20.22.46:443: i/o timeout 原因:可能是远程连接被关闭的问题,这是由于国内网络限制导致的,但是我用了梯子也不好用,解决办法:找到setting.txt文件夹,添加以下命令 root 是nvm安装路径, path 是node的环境变量路径可以不用修改 如果找不到nvm安装在哪,可以使用 everything 这个软件搜索 nvm文件夹 root: C:\Users\86173\AppData\Roaming\nvm path: C:\Program Files\nodejs node_mirror:https://npmmirror.com/mirrors/node/ npm_mirror:https://npmmirror.com/mirrors/node/ 说明:不要写以下这两句 淘宝原镜像域名(registry.npm.taobao.org)的 HTTPS 证书正式到期,想要继续使用,需要将 npm 源切换到新的源(registry.npmmirror.com)

【前端】记录各种控制台警告/bug

一、Element Plus 1、控制台警告:“Runtime directive used on component with non-element root node. The directives will not function as intended.” 错误原因:在 Vue 组件上使用了运行时指令(指那些在运行时动态绑定到 DOM 元素上的指令),但是该组件的根节点不是一个标准的 DOM 元素(例如 div 或 span) 原因:自定义指令不能放到组件上,而是要放到自有的元素上。 解决方法: 1.找到报警告的位置, 确认组件的根节点是否为一个有效的 DOM 元素 2.运行时指令:v-loading、v-show、v-if… 3.如下图示例:el-dialog上不能使用自定义指令v-loading Element UI 和 Element Plus 中的 el-dialog组件本身是一个封装好的组件,它有自己的内部结构和生命周期。当你尝试在 el-dialog 上使用 v-loading指令时,可能会遇到一些问题,主要是因为 v-loading 指令期望的是一个标准的 DOM 元素,而 el-dialog的根节点可能不是这样的元素。 2、Ignored: ResizeObserver loop limit exceeded element-plus 使用el-table 在切换tab栏时报错: 原因:ResizeObserver不能处理所有的observations导致报错; 解决方法: 1.阻止table的重绘,给每个<el-table-column>设置固定的width,缺点是无法自适应宽度。 2.给每个<el-table-column>设置min-width 3.添加debounce()防抖方法,在App.vue文件中添加: const debounce = (fn, delay) => { let timer = null; return function () { let context = this; let args = arguments; clearTimeout(timer); timer = setTimeout(function () { fn.

状态模式-系统架构师(四十二)

1、()是系统分析阶段结束后得到的工作产品,()是系统测试阶段完成后的工作产品。 问题1 A系统设计规格说明 B系统方案建议书 C系统规格说明 D单元测试数据 问题2 A验收测试计划 B测试标准 C系统测试计划 D操作手册 解析: 系统分析结束,得到了系统方案建议书。 系统测试完成,代表测试都完成了,测试计划应该在完成之前,所以测试完成之后,应该是 有了操作手册。 答案: B D 2、(信息系统基础知识)企业信息化涉及对企业管理理念的创新,按照市场发展的要求,对企业现有的管理流程重新整合,管理核心从对()的管理。 A人力资源和物资 B财务和物料 C信息技术和知识 D业务流程和数据 解析: 管理核心 财务、物料管理 转向 技术、物资、人力资源的管理。进而还要扩展到 客户关系管理、供应链管理乃至发展到电子商务。 答案:B 3、在数据库设计的需求分析阶段应当形成 需求说明文档,这些文档可以作为()阶段的设计依据。数据库设计一共哪几步阶段? A概念结构设计 B数据库运行和维护 C物理结构设计 D逻辑结构设计 解析: 数据库设计分为四个阶段: 需求分析,概要设计,逻辑设计,物理设计。 分析阶段形成 需求说明文档,数据字典和数据流程图。 作为概要设计阶段的依据。 4、ANSI/IEEE 是对软件密集型系统的架构进行描述的标准。该标准中,()这一概念主要用于描述软件架构模型。通常采用描述某个利益相关人所关注加过模型的某一方面。()则是对所有利益相关人关注点的响应和回答。 问题1 A架构风格 B上下文 C组件 D视图 解析: 视图的概念描述软件架构模型。 架构则是对所有利息相关人关注点的响应和回答。 5、(设计模式,必背)为了封装图像操作与照片特征之间的复杂逻辑关系,采用()最为合适。为了实现图像处理算法的灵活选择与替换,采用()最为合适。 解析: 封装图像操作与照片特征之间的复杂逻辑,应该是状态模式,因为状态模式将每一个分支放到一个独立的类,这样根据自身情况将状态作为一个对象。 为了实现图像处理算法的灵活选择与替换,应该是策略模式,定义一系列的算法,封装起来,使他们可以相互替换,算法可以独立于使用他的客户端。 6、在服务端构件模型的典型解决方案中,()较为合适于应用服务器。 A COM+和ASP模型 B COM+和servlet模型 C EJB和servlet模型 D EJB和COM+模型 解析: ASP的P代表page,是web应用。 Servlet也是web应用。 适合应用服务器的所以是EJB+COM+

如何将PostgreSQL的数据实时迁移到SelectDB?

PostgreSQL 作为一个开源且功能强大的关系型数据库管理系统,在 OLTP 系统中得到了广泛应用。很多企业利用其卓越的性能和灵活的架构,应对高并发事务、快速响应等需求。 然而对于 OLAP 场景,PostgreSQL 可能并不是最佳选择。 为了实现庞大规模数据的数据分析场景,企业会选择使用专业数据仓库产品。例如:ClickHouse、Doris、SelectDB、Greenplum、Redshift 等。选择数仓不得不考虑查询性能和存储效率,而 SelectDB 在这两个方面表现优异,在查询性能方面,SelectDB 采用先进的列存储和向量化执行引擎,能够高效处理复杂查询,提供卓越的查询性能;在存储效率方面,SelectDB 的列存储结构和高效压缩算法,大大减少了磁盘占用和 I/O 开销。 PostgreSQL 本文以 SelectDB 为例,介绍如何把 PostgreSQL 的数据迁移到 SelectDB 中。 数据迁移难在哪? 想象一下,如果你现在要做 PostgreSQL 到 SelectDB 的数据迁移,你需要做哪些事情? 表的初始化:SelectDB 端是不是要先创建一个和源端一致的表结构?然后才能从源端接收数据。手动进行初始化的情况下,如果 PostgreSQL 端有成百上千个表,你又该如何应对? 数据结构的映射:PostgreSQL 和 SelectDB 两者数据结构不同,这点很重要,需要确保数据从源端同步过去后还是完整的。很负责任地说一句,除非你对两者的数据模型的理解非常极致,且保证绝对不出错,才可能达到理想的结果。 实时同步的速率:让 SelectDB 端的数据时刻与源端的 PostgreSQL 保持一致。通过 SelectDB 进行数据实时分析的大前提是,当前 SelectDB 中的数据必须是最新的,分析结果才有意义。 源端 DDL 语句的联动:实时捕获源端 PostgreSQL 的 DDL 变更,并及时在目标端的 SelectDB 中同步执行。这绝对不能算是一个轻松的工作,大多数情况下,源端的数据结构发生变化时,同步链路会中断,导致迁移失败。 同步任务的稳定性:试想如果需要长期在线同步 PostgreSQL 和 SelectDB,什么最重要?当然是同步任务的稳定性。你得考虑在网络、服务器出现异常的情况下,应该怎么保证任务可用。 这些问题很关键,依靠手动或者简单的脚本,迁移效果肯定是不太好的 ,那么选择一个对的工具就至关重要了。 其实对于上述问题,NineData 有绝对的发言权,我们先来看看它的特性: 结构复制:基于目标端数据源的特性,自动高效地完成表的创建、数据结构的映射等工作。 复制性能:基于动态攒批、并行复制、Stream Load 等技术,复制性能轻松达到 200 MB/S。

【AI】可变形卷积Deformable Conv

卷积对大家来说并不陌生了,这里主要描述Deformable Conv。其在论文中也是常见的一个术语,Deformable Convolutional Networks(DCN) 还可以细分成可变形卷积、对候选区域的池化等。 传统卷积操作 将特征图分成一个个与卷积核大小相同的部分,然后进行卷积操作,每部分在特征图上的位置都是固定的。但对形变比较复杂的物体,使用这种卷积的效果就可能不太好。 对于传统卷积,可提升效果的方法有丰富数据集、数据增强、人工设计特征和算法等。但过多的数据又会造成收敛慢或需要更复杂的网络结构。 Deformable Convolutional Networks(DCN) 对于复杂形变场景,可用Deformable Conv可变形卷积来解决。Deformable Conv 在感受野中引入了偏移量(可变形卷积则在传统卷积基础上为每个点引入了一个偏移量,偏移量是由输入特征图与另一个卷积生成的,通常是小数。),而且这偏移量是可学习的,使得感受野不再是死板的方形,而是与物体的实际形状贴近,无论物体如何形变之后的卷积区域便始终覆盖在物体形状周围,实现移动、缩放尺寸、旋转等。 如图所示,(a)图为传统卷积操作,(b)©(d)均将原先的各点施加一个offset,使感受野形状改变。 由于加入偏移量后的位置非整数,并不对应feature map上实际存在的像素点,因此需要使用插值来得到偏移后的像素值,通常可采用双线性插值。 图中绿色过程为卷积学习偏移的过程,其中offset field的通道大小为2N,表示卷积核分别学习x方向与y方向的偏移量。 在input feature map上普通卷积操作对应卷积采样区域是一个卷积核大小的正方形(绿框),而可变形卷积对应的卷积采样区域为一些蓝框表示的点,这就是可变形卷积与普通卷积的区别。 一个output feature map上的点对应到input feature map上的卷积采样区域大小为KK,按照可变形卷积的操作,这KK区域的每一个卷积采样点都要学习一个偏离量offset,而offset是用坐标表示的,所以一个output要学习2KK个参数。 假设一个output大小为HW,所以一共要学习2KKHW个参数。即上图的offset field(N=KK),其维度为B2KKHW,其中B代表batch_size; 假设input feature map的维度为BCHW,一个batch内的特征图(一共C个)共用一个offset field,即一个batch内的每张特征图用到的偏移量是一样的; 可变形卷积不改变input feature map的尺寸,所以output feature map也为H x W; 参考公式 传统卷积 其中,p_{n}代表卷积核中每一个点相对于中心点的偏移量,p_{0}是输入特征图上任意一点,x(p_{0}+p_{n})表示输入特征图上p_{0}+p_{n}位置处的元素值 DCN 即输出特征图上每点(对应卷积核中心)加上其对应卷积核每个位置的相对(横、纵)坐标后再加上自学习的(横、纵坐标)偏移量。 双线性插值 将插值点位置的像素值设为其4领域像素点的加权和,领域4个点是离其最近的在特征图上实际存在的像素点,每个点的权重则根据它与插值点横、纵坐标的距离来设置,公式最后一行的max(0, 1-…)就是限制了插值点与领域点不会超过1个像素的距离。 下图表示了如何通过p12,p22,p11,p21的加权来计算出p的像素值pixel

Java中基本数据类型包装类的常量池缓存的值得范围是多少?

在Java中,基本数据类型对应的包装类(如Integer、Long、Byte等)使用了一种优化手段,称为常量池缓存(也称为缓存池或整数池)。这个缓存主要用于存储一定范围内的实例,以便快速重复利用这些对象,减少内存消耗。 对于Integer类,JDK 8及之前的版本中,这个范围是从-128到127。这意味着当你请求一个在该范围内的Integer值时,JVM会从缓存中返回一个已经创建的实例,而不是每次都创建一个新的实例。这个范围是固定的,不能被修改。 从Java 9开始,由于永久代被移除,Integer的缓存实现发生了变化,但仍然存在类似的缓存机制。Java 9中,Integer的缓存范围默认从-128到127,但这个范围可以通过JVM参数-XX:AutoBoxCacheMax=<size>进行调整。 其他包装类,如Long、Byte、Short等,也有类似的缓存机制,但具体的缓存值范围可能不同,并且可能会受到JVM实现的影响。例如,在一些JVM实现中,Long的缓存范围可能会更广。 请注意,这个缓存机制仅适用于自动装箱(autoboxing)过程,即基本数据类型与包装类之间的自动转换。如果你显式地创建包装类的新实例,如使用new Integer(123),那么每次都会创建一个新的对象,而不会使用缓存中的实例。 Byte,Short,Integer,Long 这 4 种包装类默认创建了数值 [-128,127] 的相应类型的缓存数据,Character 创建了数值在 [0,127] 范围的缓存数据,Boolean 直接返回 True or False。 如果我们使用的装箱的方式创建值为缓存范围内的对象,他会返回缓存区的对应的对象,比如Integer i = 10,就会返回缓存区中的对象,而Integer i = 1000就会在堆区创建对象。

Python 爬虫项目实战(一):爬取某云热歌榜歌曲

前言 网络爬虫(Web Crawler),也称为网页蜘蛛(Web Spider)或网页机器人(Web Bot),是一种按照既定规则自动浏览网络并提取信息的程序。爬虫的主要用途包括数据采集、网络索引、内容抓取等。 爬虫的基本原理 种子 URL:爬虫从一个或多个种子 URL 开始,这些 URL 是起点。发送请求:爬虫向这些种子 URL 发送 HTTP 请求,通常是 GET 请求。获取响应:服务器返回网页的 HTML 内容作为响应。解析内容:爬虫解析 HTML 内容,提取所需的数据(如文本、链接、图片等)。提取链接:从网页中提取出所有链接,并将这些链接加入待访问队列。重复过程:爬虫重复上述步骤,直到达到某个停止条件,如爬取了一定数量的页面,或所有页面都被爬取完毕。 爬虫的分类 通用爬虫 设计用于抓取整个互联网的大量网页。搜索引擎(如 Google、Bing)的爬虫就是通用爬虫。 聚焦爬虫 专注于特定主题或领域,抓取相关网页。比如,一个新闻爬虫只抓取新闻网站的内容。 增量爬虫 仅抓取自上次爬取以来发生变化或更新的网页,适用于动态内容更新频繁的网站。 爬虫的合法性和道德 在编写和运行爬虫时,必须遵循以下原则: 遵守网站的 robots.txt: 大多数网站都有一个 robots.txt 文件,规定了哪些页面允许被爬取,哪些不允许。爬虫应当尊重这些规则。 避免过度抓取: 设置适当的抓取频率,避免对服务器造成过大负担。 尊重版权和隐私: 不应抓取或使用受版权保护的内容,或涉及用户隐私的数据。 获取许可: 在某些情况下,最好获得网站管理员的许可,特别是当你打算频繁地抓取大量数据时。 通过以上方法和原则,可以编写高效、可靠且合规的网络爬虫来满足数据采集的需求。 侦察 打开页面 F12 检查定位关键元素 在网络中刷新页面 搜索关键字 查看在页面中的渲染情况是不是我们想要的数据,可以看到这里列出了200首歌那么就是的 在标头中确定数据来源地址及请求方法 源代码 import re import os import requests filename = 'music\\' # 如果没有则创建文件夹 if not os.path.exists(filename): os.makedirs(filename) # 请求网址(如果想要爬取其他的榜单的歌曲内容,只需要改这个 url 即可) url = 'https://music.

Gateway实现Redis拉取信息+用户模块开发

文章目录 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐)🌟 亮点功能📦 spring cloud模块概览常用工具 🔗 更多信息1.Gateway实现Redis拉取信息1.目录结构2.RedisConfig.java3.RedisUtil.java4.StpInterfaceImpl.java 2.用户模块-用户注册1.easycode生成auth_user代码1.创建好目录2.配置生成代码3.将dao层的类剪切到mapper层4.AuthUserDao.java删除Pageable的参数5.service层删除分页查询接口和实现类6.最终目录结构 2.sun-club-auth-application-controller 基本配置1.目录创建2.GlobalConfig.java mvc的全局处理 3.sun-club-auth-common 基本配置1.目录结构2.PageInfo.java3.PageResult.java4.Result.java5.IsDeleteFlagEnum.java6.ResultCodeEnum.java 4.sun-club-auth-application-controller层1.AuthUserDTO.java2.sun-club-auth-domain 模块AuthUserBO.java 与DTO一致 3.AuthUserDTOConverter.java 5.sun-club-auth-domain层1.目录创建2.AuthUserBOConverter.java3.AuthUserDomainService.java4.AuthUserDomainServiceImpl.java 6.sun-club-auth-infra层1.AuthUserService.java 修改insert返回为Integer2.AuthUserServiceImpl.java3.AuthUserDao.java4.AuthUserDao.xml 7.最后:UserController.java8.测试1.接口设计2.结果3.DB4.发现DB中没有插入status1.sun-club-auth-common模块新增枚举 AuthUserStatusEnum.java2.sun-club-auth-application-controller UserController.java新增语句3.重启测试 3.用户模块-更新用户信息1.接口设计2.sun-club-auth-application-controller1.UserController.java 3.sun-club-auth-domain1.AuthUserDomainService.java2.AuthUserDomainServiceImpl.java 4.sun-club-auth-infra1.AuthUserService.java2.AuthUserServiceImpl.java 5.测试1.结果2.DB 4.用户模块-删除用户信息1.接口设计2.sun-club-auth-application-controller1.UserController.java 3.sun-club-auth-domain1.AuthUserDomainService.java2.AuthUserDomainServiceImpl.java 4.测试1.结果2.DB 5.用户模块-启用/禁用信息1.接口设计2.UserController.java3.测试1.结果2.DB 🌞 Sun Frame:SpringBoot 的轻量级开发框架(个人开源项目推荐) 轻松高效的现代化开发体验 Sun Frame 是我个人开源的一款基于 SpringBoot 的轻量级框架,专为中小型企业设计。它提供了一种快速、简单且易于扩展的开发方式。 我们的开发文档记录了整个项目从0到1的任何细节,实属不易,请给我们一个Star!🌟 您的支持是我们持续改进的动力。 🌟 亮点功能 组件化开发:灵活选择,简化流程。高性能:通过异步日志和 Redis 缓存提升性能。易扩展:支持多种数据库和消息队列。 📦 spring cloud模块概览 Nacos 服务:高效的服务注册与发现。Feign 远程调用:简化服务间通信。强大网关:路由与限流。 常用工具 日志管理:异步处理与链路追踪。Redis 集成:支持分布式锁与缓存。Swagger 文档:便捷的 API 入口。测试支持:SpringBoot-Test 集成。EasyCode:自定义EasyCode模板引擎,一键生成CRUD。 🔗 更多信息 开源地址:Gitee Sun Frame详细文档:语雀文档

Sun Frame:基于 SpringBoot 的轻量级开发框架(个人开源项目)

文章目录 🌞 Sun Frame:基于 SpringBoot 的轻量级开发框架(个人开源项目)🚀 欢迎使用 Sun Frame🌟 项目亮点📦 模块结构🌐 Sun-Cloud📦 Sun-Common 💡 示例与演示🔗 获取更多信息 🌞 Sun Frame:基于 SpringBoot 的轻量级开发框架(个人开源项目) 一个现代化的、易于使用的轻量级开发框架,让开发变得简单高效。 🚀 欢迎使用 Sun Frame Sun Frame 是我个人制作的一款基于 SpringBoot 的轻量级开发框架,专为中小型企业设计,旨在提供快速、简单、易扩展的开发体验。无论您是新手还是经验丰富的开发者,Sun Frame 都能帮助您加速项目构建。 我们致力于打造一个可扩展、易于使用的开发框架,并提供最详细的文档支持! 如果您觉得项目对您有帮助,请不要吝啬给我们一个Star!🌟 您的支持是我们持续更新和改进的动力。 🌟 项目亮点 组件化开发:灵活选择所需组件,简化开发流程。高性能架构:通过异步日志和 Redis 缓存技术提升性能。易扩展设计:支持多种数据库和消息队列,满足多样化的业务需求。 📦 模块结构 🌐 Sun-Cloud Nacos 服务注册:提供高效的 Nacos 服务注册与发现。Feign 远程调用:集成 Feign,简化服务间的远程调用。强大网关功能:支持路由与限流的网关组件。 📦 Sun-Common 日志组件:自动记录日志,支持异步处理,支持链路追踪功能。MyBatisPlus 集成:简化数据库交互,支持自动生成 CRUD 接口。Redis 缓存:全面封装 Redis 操作,支持分布式锁。Swagger API 文档:提供便捷的 API 文档化入口。测试组件:集成 SpringBoot-Test,支持单元测试和代码覆盖率检测。常用工具类:一系列常用工具类,提升开发效率。Web 组件:支持统一异常处理和响应结果转换。对象存储组件:集成 Minio,支持文件上传和下载。RabbitMQ 集成:支持常用交换机配置,提供可靠的消息队列服务。 💡 示例与演示 大数据量 Excel 导出:轻松处理百万级数据导出。设计模式示例:快速掌握常用设计模式的应用。自定义工具和模板:支持树形结构构建和 CRUD 代码生成。 🔗 获取更多信息 项目开源地址:Gitee Sun Frame详细文档地址:语雀文档

【Python】Python中的运算符与注释

运算符与注释 导读一、注释1.1 注释的分类1.2 注释的使用1.3 注释的格式1.4 注释的要求 二、运算符的分类三、算术运算符3.1 `'+'`——加法运算符3.2 `'*'`——乘法运算符3.3 '/'与'//'——除法运算符与取整除运算符3.4 `'**'`——幂运算符 四、比较(关系)运算符五、赋值运算符六、逻辑运算符七、位运算符八、成员运算符九、身份运算符十、运算符优先级结语 导读 大家好,很高兴又和大家见面啦!!! 在上一篇内容中我们介绍了Python中的输入与输出的相关内容: Python通过内建函数input()实现输入——函数返回字符串Python通过内建函数print()实现输出——通过f-string实现格式化输出 由于输入函数的返回值为字符串,因此我们在通过input()获取输入的信息后就是需要通过一系列库函数来将获取到的字符串进一步转换成我们所需要的数据,如将字符串转换成整型的函数int(),以及分割字符串的函数split()方法; 在了解完了Python的输入与输出的内容后,接下来我们还需要知道Python中如何实现数据之间的运算。 在C语言中有一系列的操作符是专门用于进行数据之间的运算的: 算术操作符:'+'、'-'、'*'、'/'、'%'——可以实现数据的加法、减法、乘法、除法以及取模运算位运算操作符:'&'、'|'、'^'、'~'——可以实现数据的二进制位之间的运算移位操作符:'<<'、'>>'——可以移动数据的二进制位逻辑操作符:'&&'、'||'、'!'——可以进行数据之间的逻辑运算关系操作符:'>'、'>='、'=='、'<='、'<'、'!='——可以比较数据之间的大小关系赋值操作符:'='、'+='、'-='、'*='、'/='、'%='、'&='、'|='、'^='、'<<='、'>>='——可以对数据进行一系列的赋值操作 正是有了以上这些操作符,C语言才能够利用计算机进行各种复杂的数据运算。那在Python中又会有哪些与数据运算相关的操作符呢?在今天的内容中,我们将会开始探讨Python中的运算符; 一、注释 在开始介绍运算符之前,我们先了解一下在Python中应该如何对代码进行注释。 1.1 注释的分类 在C/C++中注释分为两类——单行注释与多行注释。 C/C++中通过使用双斜杠//来进行单行注释,使用/**/即可以进行单行注释可以进行多行注释,如下所示: 在VS中可以通过快捷键Ctrl + K + C进行快速注释,通过Ctrl + K + U快速取消注释。 在Python中注释同样也分为单行注释与多行注释,只不过与C/C++不同的是,Python中的注释是通过#与三引号''''''、""""""来实现的,如下所示: 在Python中,多行注释实际上也是一种字符串,虽然多行字符串在这里被当作多行注释使用,但它实际上是一个字符串,我们只要不使用它,它不会影响程序的运行。 这些字符串在代码中可以被放置在一些位置,而不引起实际的执行,从而达到注释的效果。 在PyCharm中,我们可以通过快捷键Ctrl + /来进行快速单行注释以及取消单行注释。 1.2 注释的使用 在计算机语言中,注释是用来帮助程序员更好的理解代码的运行逻辑。注释常用来对一些比较复杂的代码进行母语解释。单行注释的位置常在代码的上一行,或者代码的右侧,少数情况下用在代码的下方,如下所示: # 注释的使用 # 创建一个变量 a = 10 # 该变量类型为整型 # 注释很少位于代码的下方 要注意的是,通过注释符#进行注释时,注释符的右侧都是注释的内容,因此注释不会出现在代码的左侧。 多行注释的位置常放在代码或文件开头,用来对相应功能或文件内容进行说明,如下所示: 这里需要注意的是在进行多行注释时,既可以使用由三个单引号组成的三引号,也可以使用由三个双引号组成的三引号。 现在我们已经知道了如何在Python中来使用注释了,下面我们就来看一下不同注释的使用格式; 1.3 注释的格式 在使用单行注释时,我们需要保证以下格式: 注释符#与注释内容之间需要通过一个空格隔开: # 注释内容,中间有一个空格 当注释在代码右侧时,代码与注释符之间需要通过至少两个空格隔开: a = 10 # 注释符与代码之间至少要有两个空格 在使用多行注释时,需要注意以下几点:

【Qt】如何搭建Qt开发环境

Qt的开发工具 需要搭建Qt开发环境,需要安装3个部分: C++编译器(gcc、cl.exe...)注意,这里的C++编译器不是指visual studio这种集成开发环境,编译器不等于IDE,编译器只是IDE调用的一个程序。Qt SDK。SDK被称为软件开发工具包,就比如,Windows版本的Qt SDK里面已经内置了C++的编译器,其内置的编译器是mingw,mingw是Windows版本的gcc/g++,在具体安装的过程中,需要把对应的C++编译器勾选上。如果想要VS内置的cl.exe作为编译器,需要配置很多额外的东西,容易出错。需要有一个Qt的集成开发环境(IDE)。 Qt支持多种开发工具,其中比较常用的开发工具有:Qt Creator、visual Studio、Eclipse。 Qt Creator Qt Creator 是⼀个轻量级的跨平台集成开发环境(IDE),专为使⽤ Qt 框架进⾏应⽤程序开发⽽设计。它是⼀个功能强⼤、易于使⽤、快速且⾼效的⼯具,被⼴泛⽤于编写各种类型的应⽤程序,如桌⾯应⽤程序、移动应⽤程序和嵌⼊式系统等。 Qt Creator 提供了⼀个可视化的界⾯设计器和代码编辑器,可以帮助开发者更快捷地创建复杂的⽤⼾界⾯和处理各种事件。它还包含了调试⼯具、版本控制⼯具、⾃动完成和智能提⽰等功能,以及⽀持多语⾔和跨平台的开发环境。 Qt Creator的主要特定是: 紧密集成的 Qt 框架:Qt Creator 专⻔为 Qt 开发⽽设计,因此它与 Qt 框架集成得⾮常紧密,使开发者可以更容易地管理和部署他们的应⽤程序。 强⼤的编辑器:Qt Creator 具有⼀些先进的编辑器功能,如语法⾼亮、代码折叠、智能提⽰、⾃动完成和代码重构。 集成的调试器:Qt Creator 内置了调试器,允许开发⼈员在代码中设置断点以及检查变量、堆栈和调⽤树等信息。 ⾼效的构建系统:Qt Creator 提供了⼀个⾼效的构建系统,可以⾃动构建和部署应⽤程序,同时⽀持使⽤不同的编译器和平台。 可视化界⾯设计器:Qt Creator 具有⼀个可视化界⾯设计器,它允许开发⼈员在没有编写代码的情况下创建复杂的⽤⼾界⾯。 多语⾔⽀持:Qt Creator ⽀持多种编程语⾔,包括 C++、QML、JavaScript 等。 Qt Creator 是⼀个功能⻬全、易于使⽤且⾼效的跨平台 IDE,适⽤于各种类型的应⽤程序开 发,特别是那些使⽤ Qt 框架的开发者。 总之,Qt Creator是Qt官方提供的,是最容易入门,最容易上手的的一种方式,不需要额外的配置,虽然Qt Creator在使用过程中存在不少bug,有些bug非常影响使用体验,但是整体来说,用起来还是比较方便的,比较适合初学者。 Visual Studio Visual Studio 是由微软公司开发的集成开发环境(IDE)。它可以⽤来开发多种类型的应⽤程序。包括Windows 桌⾯应⽤程序、Web应⽤程序、移动应⽤程序、游戏等。Visual Studio 提供了丰富的开发⼯具和功能,包括代码编辑器、调试器、⾃动完成、代码重构、版本控制等等。它⽀持多种编程语⾔,如:C++、C#、Visual Basic、F#、Python等。Visual Studio 还可以与其他开发⼯具和服务集成,如Azure 云服务、GitHub、Jenkins等。 Visual Studio的主要特点: 多语⾔⽀持:Visual Studio ⽀持多种编程语⾔,包括 C++、C#、Visual Basic、F#、Python、JavaScript 等。 丰富的⼯具集:VS 提供了各种开发⼯具,包括代码编辑器、调试器、代码分析⼯具等,以提⾼开发⼈员的效率。 可视化设计:VS提供了可视化的设计⼯具,如窗体设计器、WPF 设计器等,使开发⼈员可以直观地设计⽤⼾界⾯。 跨平台开发:VS ⽀持跨平台开发,可以开发适⽤于 Windows、Linux 和 macOS 等多个平台的应⽤程序。 集成的调试器:VS 集成了强⼤的调试器,可以进⾏代码的单步调试、断点调试等操作来帮助开发⼈员查找和修复错误。 丰富的扩展性:VS 可以通过安装扩展来扩展其功能,开发⼈员可以根据⾃⼰的需求选择并安装适合的扩展。 Visual Studio 这个集成开发环境是比较优秀,功能更强的,但是额外配置很多,而且更加容易出错。有些公司开发商业Qt程序的时候,可以使用VS,在使用vs的过程中,需要给vs安装插件,并且需要把Qt SDK使用VS的编译器重新编译,对于现在的VS而言,有预编译好的版本,也比较方便。

【数据结构】map&set详解

🍁1. Set系列集合 Set接口是一种不包含重复元素的集合。它继承自Collection接口,所以可以使用Collection所拥有的方法,Set接口的实现类主要有HashSet、LinkedHashSet、TreeSet等,它们各自以不同的方式存储元素,但都遵循Set接口的规定。 当你需要确保集合中的元素唯一时。当你不需要保持元素的插入顺序时(除非使用LinkedHashSet)。当你需要元素自然排序或根据自定义排序规则排序时(使用TreeSet)。 🍁1.1 HashSet 当用HashSet实例化对象时,由于底层结构是哈希表,所以元素是无序的,而TreeSet底层是红黑树,是有序的 由于Set系列集合里面不能有重复的元素,在之前我们也了解到,add方法的返回值是boolean类型的,当遇到重复元素,第二次添加就会添加失败 并且Set集合没有索引的概念,不能通过下标的方式进行遍历打印 和之前一样,没有索引的集合可以通过迭代器,增强for,lambda表达式进行遍历 Iterator<String> it = s1.iterator(); while (it.hasNext()){ System.out.print(it.next() + " "); } System.out.println(); for(String s : s1){ System.out.print(s + " "); } System.out.println(); s1.forEach(new Consumer<String>() { @Override public void accept(String s) { System.out.print(s + " "); } }); 🍁1.2 LinkedHashSet LinkedHashSet底层也是哈希表,但是存取元素的顺序是一致的,因为使用了双向链表记录添加顺序 🍁1.3 TreeSet TreeSet是基于红黑树实现的,TreeSet中的元素处于排序状态,因此查找、添加、删除和遍历等操作都能以对数时间复杂度进行。但是,向TreeSet中添加的元素必须实现Comparable接口,或者在创建TreeSet时提供一个Comparator对象,以确保元素可以被正确地排序。 排序规则:Integer,Double等数值类型默认按照从小到大的顺序排序,对于字符,字符串类型,按照ASCII码表中的数字进行升排序 接下来演示一下,创建自定义类型的TreeSet 例如:给出一个Student类,要求按照学生的年龄排序 首先创建好Student类之后,需要实现Comparable接口,然后重写compareTo和toString方法 public class Student implements Comparable<Student>{ public String name; public int age; public Student(String name, int age) { this.

【游戏引擎之路】登神长阶(九)——《3D游戏编程大师技巧》:我想成为游戏之神!

5月20日-6月4日:攻克2D物理引擎。 6月4日-6月13日:攻克《3D数学基础》。 6月13日-6月20日:攻克《3D图形教程》。 6月21日-6月22日:攻克《Raycasting游戏教程》。 6月23日-7月1日:攻克《Windows游戏编程大师技巧》。 7月2日-7月6日:攻克《雅达利2600汇编游戏开发》。 7月7日-7月11日:攻克《x86/x64汇编语言》。 7月11日-7月22日:学习《3D游戏编程大师技巧》(阶段性)。 7月14日-7月18日:学习《游戏引擎架构》(完成)。 7月23日-7月30日:攻克Python语言学习。 7月31日-8月5日:攻克《3D游戏编程大师技巧》。 下个目标《DirectX12 3D 游戏开发实战》。 (一)近况总结 从6月开始的时候,我当时不知道为什么,好像找到了人生的目标,所以动力非常足。从6月4号开始,到今天为止,我没有休息过一天。星期六,星期天都在工作。但是我终于被我的抑郁症反噬了。本来《3D游戏编程大师技巧》还有阴影一个小节我还没有实现。但是当我学习的时候,脑子里面一波一波地头痛,这是我的抑郁症和神经衰弱的并发症,只要一透支脑力,就会痛。 本来我打算到国庆之前都不休息的,来一个史诗级的远征。但是看来坚持不下去了。于是,这个里程碑到此结束,我的最长工作记录——2个月不休息。即便是没有抑郁症之前,我也没有2个月不休息过,只不过那时我只是不想做,而不是没能力做。 休息两天,再整装出发吧。 (二)《3D游戏编程大师技巧》学习总结 今天终于把《3D游戏编程大师技巧》全部攻略完成。最后一个实现的是透明材质,其实还有阴影部分没有实现。但是阴影部分因为都需要Alpha混合,而我的引擎加上了Alpha混合之后变得巨卡,我也不打算做下去了。反正这个软光栅的学习也是一个学习,并不是真正制作引擎。 我的下一个学习目标是《DirectX12 3D 游戏开发实战》,这是真正能够用于制作实用的引擎了。其实《3D游戏编程大师技巧》(还有他的姐妹篇《Windows游戏编程大师技巧》)被称为游戏编程四大坑书之首不是没有道理的。因为里面用到的技术不仅老旧,在现在看来也没什么价值。比如说8位模式,我的显示器已经没办法支持8位模式了。 但是,如果你知道自已想要什么,这本书仍然不失为一个经典。他坑的原因不仅是因为难,而且因为繁杂,其实这本书的前半,作者还坚持给每个渲染管线8位和16位的版本,到后面他自已可能都觉得麻烦了,只留下了16位版本。 我在学这本书之前还学了《3D图形教程》。这也是一个软件光栅化的教程。比这本书深入浅出得多。只不过内容并没有这本书里面的丰富。 但是这段旅程我相信是有价值的。 (三)游戏之神是什么? 在这本书里面,序言中提到了这样一个事情。在游戏行业中,有两种人,一种是擅长技术的,一种是擅长设计的。很多擅长技术的人,游戏感不一定很好,他们不会设计有意思的游戏。而“游戏感”强的人,也很少有人有强大的动手能力,能自已捣鼓出游戏。而《3D游戏编程大师技巧》的作者正好是这两者都非常强的人。 其实这在游戏行业里面,这并不是什么问题。因为游戏不是一件艺术品,他是一个工程,是需要很多人通力合作做出来的。就像是卡马克有他自已的搭档罗梅洛一样。 在我心中,卡马克是游戏行业中的唯一真神,不仅仅是因为他的能力,而且是因为他的理念,我的自由软件的理念受他的影响很大。我的《薪火引擎》自然也会开源的。 然而,即便是卡马克,他离真正的“游戏之神”也有一定的距离。因为他的技术力虽然非常强,但是对于游戏设计却并不痴迷。 “游戏之神”是什么? 但在我的心中,游戏之神一定是“制作游戏”和“设计游戏”都非常强的人。如果说一个设计者自已都做不出来游戏,怎么能称为游戏之神呢?那只是伪神而已。 当然了,这仅仅是我自已的信念,不能用这个去评价别人,而且也没有事实上的操作价值。因为每个人专精于自已的领域,比如说设计游戏的专精于设计,制作游戏的专精于制作,然后两人合作,才是是正道。 可是,游戏之神是什么,这是人类向上帝的提问,没有人拥有权威,谁都可以定义自已心中的游戏之神。 我真的希望自已成为那个“真神”。当我有天用自已的引擎做出《三千神界》的时候,我就可以说我做到了这一点。 因为我相信,当有一天我能站在那个地方的时候,能够看到不一样的风景。

如何在亚马逊云科技AWS上利用LoRA高效微调AI大模型减少预测偏差

简介: 小李哥将继续每天介绍一个基于亚马逊云科技AWS云计算平台的全球前沿AI技术解决方案,帮助大家快速了解国际上最热门的云计算平台亚马逊云科技AWS AI最佳实践,并应用到自己的日常工作里。 在机器学习和人工智能领域,生成偏差(Generative Bias) 是指在生成模型或生成式算法中所引入的偏差。生成偏差可能导致模型生成的输出结果不公平、不准确或不符合预期。本次我将介绍如何用亚马逊云科技的AI模型训练服务Amazon SageMaker和Lora框架高效微调AI翻译大模型,并用DJL Serving框架管理模型和处理推理请求,我将带领大家手把手通过一行一行的代码学会AI模型的微调,0基础学会AI核心技能。本架构设计还包括了与用户交互的前后端应用,全部采用了云原生Serverless架构,提供可扩展和安全的AI应用解决方案。本方案架构图如下 项目开发背景知识 Dolly 3B 大模型介绍 Databricks 的dolly-v2-3b 是一种基于Databricks 机器学习平台训练的指令跟随大型语言模型,可以用于商业用途,专为自然语言处理任务而设计。它能够理解和生成多种语言的文本,支持翻译、摘要、问答等多种应用场景。Dolly 3B 拥有30亿个参数,具备强大的语言理解和生成能力。通过大规模的预训练数据集和复杂的模型架构,Dolly 3B 在处理复杂的语言任务时表现出色。 使用 Dolly 3B,开发者可以轻松实现跨语言翻译、文本生成和语义分析等任务。此外,Dolly 3B 还支持在特定领域内的定制化微调,使其在特定应用场景中表现更加精准和高效。 什么是微调 微调是指在预训练模型的基础上,通过在特定任务或领域的数据集上进行进一步训练,以提高模型在特定应用场景中的表现。微调的过程通常涉及以下几个步骤: 选择预训练模型:选择一个已经在大规模数据集上预训练过的模型,如 Dolly 3B。准备微调数据:收集和整理适用于特定任务或领域的数据集。这些数据可以包括分类、回归、翻译等任务的示例。设置训练参数:根据具体任务调整训练参数,如学习率、批量大小和训练轮数等。进行微调训练:使用准备好的数据和训练参数对预训练模型进行进一步训练,使其在特定任务上的表现得到优化。评估和部署:评估微调后的模型在验证集上的性能,并将其部署到实际应用中。 通过微调,开发者可以将通用的预训练模型转变为针对特定任务高度优化的模型,从而提升其在实际应用中的准确性和效率。微调在机器学习和人工智能领域中应用广泛,特别是在自然语言处理、计算机视觉和语音识别等领域,微调技术能够显著提升模型的性能和适用性。 本方案包括的内容: 使用大语言模型Dolly进行自然语言翻译。 评估翻译的性能和偏差。 生成数据集微调 Dolly-3B 模型。 在 Amazon SageMaker 上部署微调后的模型。 将 SageMaker API 接口集成到实际软件应用中,构建前后端云原生架构。 项目搭建具体步骤: 1. 打开亚马逊云科技控制台,进入SageMaker服务,创建一个Jupyter Notebook实例并进入。 2. 新建一个Notebook,接下来我们开始Dolly德译英翻译模型的微调。首先我们安装必要的依赖 %%capture !export TOKENIZERS_PARALLELISM=false !pip3 install -r requirements.txt !pip install sagemaker --quiet --upgrade --force-reinstall import warnings warnings.filterwarnings('ignore') 3. 接下来导入必要的依赖

【C++】list介绍以及模拟实现(超级详细)

欢迎来到我的Blog,点击关注哦💕 list的介绍和模拟实现 前言`list`介绍标准库容器` std::list` 与 `std::vector` 的优缺点缺点 `list`的基本操作构造函数`list iterator``list capcacity``list modify` `list`模拟实现存贮结构(双向带头循环)`iterator``iterator`结构`operator!=` `operator ==``operator++``operator--` `list`数据结构构造函数list的初始化节点初始化迭代器 `list modify`inserterase头插、头删、尾插、尾删 `list operator`交换clear 源码 前言 string vector的是存储是基于物理空间上连续的,而list是作为线性的链式结构,是值得学习的。 list介绍 std::list是C++标准模板库(STL)中的一个容器适配器,它内部实现为双向链表结构。这种设计使得std::list能够在常数时间内进行任意位置的插入和删除操作,这是其相对于其他序列容器如std::vector的显著优点。std::list不支持随机访问,即无法直接通过索引来访问容器中的元素,这通常需要从头部或尾部开始迭代到目标位置. 标准库容器 std::list 与 std::vector 的优缺点 std::list: 作为一个双向链表,std::list 在插入和删除操作上具有优势,因为这些操作只涉及到改变相邻节点的指针,而不需要移动其他元素。此外,std::list 不需要预分配额外的内存,可以更好地处理动态内存分配,减少内存碎片.std::vector: 作为一个动态数组,std::vector 提供了高效的随机访问能力,可以通过下标直接访问任意位置的元素,其访问效率为 O(1). 此外,std::vector 通常具有较高的空间利用率和缓存友好性,因为其元素在内存中是连续存储的. 缺点 std::list: 由于非连续的内存存储,std::list 在访问元素时效率较低,因为可能需要从头开始遍历链表。此外,每个节点都需要存储额外的指针信息,这增加了内存开销.std::vector: 在 std::vector 的中间位置插入或删除元素可能会引起大量元素的移动,以维持内存的连续性,这会导致较差的性能。当 std::vector 的容量不足以容纳新增元素时,还需要进行动态扩容,这是一个成本较高的操作 vectorlist底层 结构动态顺序表,一段连续空间带头结点的双向循环链表随 机 访 问支持随机访问,访问某个元素效率O(1)不支持随机访问,访问某个元素 效率O(N)插 入 删 除任意位置插入和删除效率低,需要搬移元素, 时间复杂度为O(N),插入时有可能需要增容, 增容:开辟新空 间,拷贝元素,释放旧空间,导致效率更低任意位置插入和删除效率高,不 需要搬移元 素,时间复杂度为 O(1)插 入 删 除底层为连续空间,不容易造成内存碎片,空间利用率 高,缓存利用率高底层节点动态开辟,小节点容易 造成内存碎片,空间利用率低, 缓存利用率低迭 代 器原生态指针对原生态指针(节点指针)进行封装迭 代 器 失 效在插入元素时,要给所有的迭代器重新赋值,因为插入 元素有可能会导致重新扩容,致使原来迭代器失效,删 除时,当前迭代器需要重新赋值否则会失效插入元素不会导致迭代器失效, 删除元素时,只会导致当前迭代 器失效,其他迭代器不受影响使 用 场 景需要高效存储,支持随机访问,不关心插入删除效率大量插入和删除操作,不关心随 机访问 list的基本操作 构造函数 【C++】vector介绍以及模拟实现接口说明list (size_type n, const value_type& val = value_type())构造的list中包含n个值为val的元素list()构造空的listlist (const list& x)拷贝构造函数list (InputIterator first, InputIterator last)用[first, last)区间中的元素构造list list iterator 此处,大家可暂时将迭代器理解成一个指针,该指针指向list中的某个节点。

【C++】vector介绍以及模拟实现(超级详细)

欢迎来到我的Blog,点击关注哦💕 【C++】vector介绍以及模拟实现 前言vector介绍 vector常见操作构造函数iteratorcapacitymodify `vector`模拟实现存储结构默认构造函数构造函数拷贝构造函数赋值运算符重载析构函数 容量(capacity)`size`和`capzcity`reserveresize 修改(modify)push_back直接将`_finsih`位置解引用赋值,`++_finsih` pop_backinserterase 元素访问(Element access)operator [ ] 迭代器(iterator) 源码 前言 string的特性和用法以及底层的探索已经,虽然string不算container的成员之一,但是也见到了其的影子,接下来让我们看看vector vector介绍 vector 是 C++ 标准模板库(STL)中的一个动态数组容器,它提供了动态大小调整和高效的随机访问功能。vector 的元素在内存中是连续存储的,这意味着可以通过指针或索引高效地访问元素。vector 自动管理其内部使用的内存,不需要手动分配和释放,支持常见容器操作,如插入、删除、遍历等. vector常见操作 构造函数 (constructor)构造函数声明接口说明vector(size_type n, const value_type& val = value_type())构造并初始化n个valvector (const vector& x); (重点)拷贝构造vector (InputIterator first, InputIterator last);使用迭代器进行初始化构造 iterator 函数声明接口说明begin + end返回第一个元素的迭代器+返回最后一个元素下一个位置的迭代器rbegin + rend返回第一个元素的reverse_iterator,即end位置,返回最后一个元素下一个位置的 reverse_iterator,即begin位置 capacity 函数声明接口说明capacity获取容量大小sizesize 获取数据个数empty判断是否为空resize改变vector的sizereserve改变vector的capacity modify vector增删查改接口说明push_back(重点)尾插pop_back (重点)尾删find查找。(注意这个是算法模块实现,不是vector的成员接口)insert在position之前插入valerase删除position位置的数据swap交换两个vector的数据空间operator[]像数组一样访问 vector模拟实现 存储结构 结构上使用命名空间myvector进行封装,防止与库冲突,使用class封装成为对象vector 这样typedef的一点是和STL保持一致 写vector写成类模板,可以支持存贮多种类型数据_start表示数据存储的开始地址_finish表示数据存贮的的下一个地址_end_of_storage表示数据当前开辟的最大空间的地址 namespace myvector { template<class T> class vector { public: typedef T* iterator; typedef const T* const_iterator; private: iterator _start; iterator _finish; iterator _end_of_storage; }; } 默认构造函数 构造函数 初始化是使用的都是空指针 vector() :_start(nullptr) , _finish(nullptr) , _end_of_storage(nullptr) {} 使用n个val初始化对象 vector(size_t n, const T& val = T()) { resize(n, val); } 根据可以模板的嵌套的性质,再次进行模板的定义这是使用两个迭代器的进行初始化 template<class InputIterator> vector(InputIterator first, InputIterator last) { while (first !

移情别恋c++ ദ്ദി˶ー̀֊ー́ ) ——2.类和对象(中(2))

5. 赋值运算符重载 5.1 运算符重载 • 重载运算符函数的参数个数和该运算符作⽤的运算对象数量⼀样多。⼀元运算符有⼀个参数,⼆元 运算符有两个参数,⼆元运算符的左侧运算对象传给第⼀个参数,右侧运算对象传给第⼆个参数。 • 如果⼀个重载运算符函数是成员函数,则它的第⼀个运算对象默认传给隐式的this指针,因此运算 符重载作为成员函数时,参数⽐运算对象少⼀个。 • 运算符重载以后,其优先级和结合性与对应的内置类型运算符保持⼀致。 • 不能通过连接语法中没有的符号来创建新的操作符:⽐如operator@。 .* :: sizeof ?: . 注意以上5个运算符不能重载。(选择题⾥⾯常考,⼤家要记⼀ 下) • 重载操作符⾄少有⼀个类类型参数,不能通过运算符重载改变内置类型对象的含义,如: int operator+(int x, int y) • ⼀个类需要重载哪些运算符,是看哪些运算符重载后有意义,⽐如Date类重载operator-就有意 义,但是重载operator+就没有意义。 • 重载++运算符时,有前置++和后置++,运算符重载函数名都是operator++,⽆法很好的区分。 C++规定, 后置++重载时,增加⼀个int形参,跟前置++构成函数重载,⽅便区分。 #include<iostream> using namespace std; class Date { public: Date(int year = 1, int month = 1, int day = 1) { _year = year; _month = month; _day = day; } void Print() { cout << _year << "

【数据结构】LinkedList与链表

目录 链表 1、链表的概念及结构 2、LinkedList的使用 2、1什么是LinkedList 2、2LinkedList的使用 3、LinkedList的遍历 4、LinkedList的模拟实现 5、ArrayList和LinkedList的区别 上篇已经熟悉了ArrayList的使用,ArrayList底层使用数组来存储元素。由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移,时间复杂度为O(n),效率比较低,因此ArrayList不适合做任意位置插入和删除比较多的场景。 因此,java集合中又引入了LinkedList,即链表结构。 链表 1、链表的概念及结构 链表 是一种 物理存储结构上非连续 存储结构,数据元素的 逻辑顺序是通过链表中的引用链接次序实现的 。 实际中链表的结构非常多样,以下情况组合起来就有 8 种链表结构: 链表大分类 单向或者双向 带头或者不带头 循环或者非循环 虽然有这么多的链表的结构,但是我们重点掌握两种 : 无头单向非循环链表 : 结构简单 ,一般不会单独用来存数据。实际中更多是作为 其他数据结构的子结构 ,如 哈希桶、图的邻接表等等。另外这种结构在笔试面试 中出现很多。 无头双向链表 :在 Java 的集合框架库中 LinkedList 底层实现就是无头双向循环链表。 2、LinkedList的使用 2、1 什么是LinkedList LinkedList官方文档 LinkedList的底层是双向链表结构( 链表后面介绍 ) ,由于链表没有将元素存储在连续的空间中,元素存储在单独的节 点中,然后通过引用将节点连接起来了,因此在在任意位置插入或者删除元素时,不需要搬移元素,效率比较高。 在集合框架中,LinkedList也实现了List接口,具体如下: 【说明】 LinkedList实现了List接口 LinkedList的底层使用了双向链表 LinkedList没有实现RandomAccess接口,因此LinkedList不支持随机访问 LinkedList的任意位置插入和删除元素时效率比较高,时间复杂度为O(1) LinkedList比较适合任意位置插入的场景 2、2 LinkedList的使用 LinkedList 的构造 方法解释LinkedList ( )无参构造Public LinkedList ( Collection<? extends E> c ) 使用其他集合容器中元素构造List public static void main ( String [] args ) { // 构造一个空的 LinkedList List < Integer > list1 = new LinkedList <> (); List < String > list2 = new java .