Java中的Stack(栈)(如果想知道Java中有关Stack的知识点,那么只看这一篇就足够了!)

前言:栈(Stack)是一种基础且重要的数据结构,以其后进先出(LIFO, Last In First Out)的特性广泛应用于计算机科学和编程中。 ✨✨✨这里是秋刀鱼不做梦的BLOG ✨✨✨想要了解更多内容可以访问我的主页秋刀鱼不做梦-CSDN博客 先让我们看一下本文大致的讲解内容: 目录 1.栈的初识 2.栈的自我实现 (1)数组实现: (2)链表实现 3.栈中常用API 4.栈的应用场景 5.总结 1.栈的初识 在开始学习使用栈之前,先让我们来了解一下什么是栈: 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。 栈的主要特性包括: 后进先出(LIFO):最新压入栈的数据最先被弹出。栈顶操作:所有的插入(push)和删除(pop)操作都只能在栈顶进行。 如果使用我们日常生活中的案例来解释的话,就如同子弹弹夹,先装入的子弹后被打出,后装入的子弹,先被打出: 将其转换为编程语言图像(如图): 其中: ——压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。 ——出栈:栈的删除操作叫做出栈。出数据在栈顶。 通过上述的讲解,这样我们就大致的了解了什么是栈(Stack)了! 2.栈的自我实现 学习完了什么是栈之后,然我们试试能不能使用已有的知识体系来实现栈,在Java中自我实现栈的方式大致有两种:使用数组实现与使用链表实现。 (1)数组实现: public class ArrayStack { public int[] stack; // 用于存储栈元素的数组 public int top; // 栈顶索引 public ArrayStack(int size) { stack = new int[size]; // 初始化数组大小 top = -1; // 初始化栈顶索引为-1,表示栈为空 } // 将元素压入栈顶 public void push(int value) { if (top == stack.

《软件开发因 AIGC 而变:机遇、挑战与开发者的抉择》

#AI是在帮助开发者还是取代他们?# 在当今科技飞速发展的时代,软件开发领域正在经历一场由生成式人工智能(AIGC)引发的深刻变革。AIGC 正以前所未有的强大力量,重塑着开发者的工作方式,无论是代码生成、错误检测还是自动化测试,AIGC 工具都逐渐从辅助角色转变为开发者不可或缺的得力伙伴。 带来的变革: 高效的代码生成 AIGC 展现出了令人惊叹的代码生成能力。它能够根据开发者提供的详细需求描述,迅速而精准地生成初步的代码框架。例如,当开发者计划构建一个功能丰富的电子商务网站时,只需向 AIGC 工具清晰地阐述诸如用户注册与登录、商品展示与搜索、购物车与结算流程等核心功能需求,AIGC 就能快速生成涵盖前端页面布局、后端数据库操作以及中间业务逻辑处理的全面代码结构。这不仅极大地缩短了项目启动阶段的时间成本,还为开发者提供了一个良好的起点,使其能够更快地进入实质性的开发和优化工作。 像 OpenAI 的 Codex 这样先进的 AIGC 模型,更是能够理解自然语言中复杂且微妙的语义和逻辑关系,从而生成高度定制化且符合特定业务场景的代码片段。比如,当需要实现一个复杂的数据挖掘算法或者实时流媒体处理模块时,Codex 能够依据开发者给出的详细规格和约束条件,生成高效且准确的代码实现,为解决高难度的技术挑战提供了有力的支持。 精准的错误检测 AIGC 在错误检测方面表现出了卓越的能力。它可以迅速且全面地扫描大量代码,凭借其强大的模式识别和机器学习算法,准确识别出潜在的错误和漏洞。在一个涉及金融交易系统的大型企业级应用中,AIGC 工具能够深入到代码的每一个角落,快速定位到诸如可能导致资金计算错误的细微逻辑偏差、容易引发系统崩溃的内存泄漏隐患,以及在高并发场景下可能出现的线程安全问题等难以察觉的关键错误,从而显著提高了代码的质量和系统的稳定性。 像 Google 的 Error Prone 这类先进的错误检测工具,利用前沿的机器学习算法和深度学习神经网络,对代码进行多层次、多角度的深度分析。它不仅能够发现常见的语法错误和编程逻辑失误,还能提前预警那些由于复杂的业务逻辑交织而可能在特定场景下才会暴露的潜在错误,为软件开发的质量保障提供了坚实的防线。 智能的自动化测试 AIGC 为自动化测试带来了全新的智能维度。它能够根据软件的功能需求和设计规格,自动生成全面且有效的测试用例,覆盖各种边界情况、异常场景以及复杂的逻辑组合,确保软件在各种极端条件下仍能保持稳定可靠的性能。例如,对于一个在线教育平台的课程管理系统,AIGC 可以自动生成涵盖课程创建、更新、删除、学员注册与选课等多个功能模块的大量测试用例,包括模拟高并发用户访问、异常网络环境以及数据库故障等极端情况,从而对系统的健壮性进行全面而深入的检验。 像 Test.ai 这样领先的自动化测试平台,充分运用人工智能技术,不仅能够自动执行这些精心生成的测试用例,还能对测试结果进行实时的智能分析。它可以快速识别出测试失败的案例,并通过智能回溯和错误诊断功能,准确指出导致测试失败的具体代码位置和可能的原因,极大地提高了测试效率和效果,为软件的高质量交付提供了有力保障。 引发的讨论: 然而,AIGC 的广泛应用在带来显著优势的同时,也不可避免地引发了对开发者职业前景和技能需求变化的广泛而深入的讨论。 一方面,部分观点担忧 AIGC 的强大功能可能会逐渐取代开发者的部分工作,尤其是那些相对基础和重复性较高的任务。毕竟,随着 AIGC 技术的不断进化和完善,它能够完成越来越多原本需要人工投入大量时间和精力才能完成的工作,这无疑给部分初级开发者的职业发展带来了一定的压力和不确定性。 另一方面,更多的理性声音认为 AIGC 实际上更多地是在助力开发者,而非简单地替代。 专注于创新和复杂问题解决 AIGC 的出现使开发者得以从繁琐的基础工作中解脱出来,将更多的时间和精力投入到创新性的工作和解决复杂的业务问题上。例如,在金融科技领域,面对日益严格的监管要求和瞬息万变的市场环境,开发者可以利用 AIGC 工具处理常规的代码编写和简单的错误排查,从而将更多的心思花在设计更安全、高效且合规的交易算法上,以满足行业的高标准和客户的多样化需求。 像在医疗健康领域的软件开发中,开发者可以借助 AIGC 的辅助,快速搭建起基本的系统框架,然后集中精力研究如何运用人工智能技术实现更精准的疾病诊断模型,或者优化医疗数据的隐私保护机制,为推动医疗行业的数字化转型贡献更具价值的智慧和创新。 提升开发效率和质量 AIGC 显著地帮助开发者加快了软件开发的速度,同时提高了软件的质量。通过快速生成准确的代码和及时检测潜在错误,减少了开发周期中的重复劳动和错误率。比如,在移动应用开发的激烈竞争环境中,AIGC 能够帮助开发者在更短的时间内推出功能更完善、性能更优越的应用版本,满足用户对新功能和优质体验的急切期待。 例如在企业资源规划(ERP)系统的开发过程中,AIGC 可以协助生成高效的数据库查询语句和优化业务流程的代码逻辑,从而减少系统的响应时间,提高企业运营效率,为企业创造更大的价值。 促进技能升级 AIGC 的发展推动着开发者不断提升自身的技能水平,掌握与 AIGC 协作的先进方法,以及更深入的算法和系统设计知识。开发者需要学会如何有效地利用 AIGC 工具提供的丰富资源和智能建议,并对其生成的结果进行合理的评估、优化和整合。比如,开发者应当具备对 AIGC 生成的代码进行质量审查和性能调优的能力,确保其符合项目的特定要求和行业的最佳实践。

交易-软件科技股F4(kafka、NET、snow、MongoDB)

先上结论,这四家公司本人是经过总结后,比较推荐的公司,可以各买10% Cloudflare, Inc. (代码: NET) 全球内容分发网络(CDN):Cloudflare通过其遍布全球的CDN优化内容的交付速度和可靠性。 DDoS攻击防护:该公司提供领先的DDoS防护服务,以保护客户免受大规模网络攻击的影响。 Web应用防火墙(WAF):Cloudflare的WAF服务增强了网站的安全性,通过阻止恶意流量来保护客户免受应用层攻击。 MongoDB, Inc. (代码: MDB) MongoDB数据库:非关系型数据库,它以其灵活的文档模型和高性能而受到开发者的青睐。 MongoDB Atlas:这是MongoDB的数据库即服务(DBaaS)解决方案,提供了一个全托管的云数据库服务。 MongoDB Stitch:作为后端即服务(BaaS)平台,它允许开发者构建应用程序而无需管理数据库后端。 Snowflake Inc. (代码: SNOW) 数据仓库即服务:Snowflake提供一个完全托管的云数据仓库服务,支持弹性伸缩和分离计算与存储的功能。 多云架构:Snowflake的平台可以在AWS、GCP和Azure等多个云服务提供商上运行,支持跨云数据操作。 数据共享:Snowflake的独特数据共享功能允许组织在不复制数据的情况下安全地共享实时数据。 Confluent, Inc. (代码: CFLT) Apache Kafka支持:Confluent由Apache Kafka的原始开发者创立,提供企业级支持和增强的Kafka服务。 Confluent Platform:一个完整的流数据服务平台,提供数据流处理、连接器、Kafka流管理和监控等功能。 Confluent Cloud:这是一个完全托管的Kafka服务,它允许用户在云中轻松地构建和运行实时数据流应用。 ksqlDB:Confluent开发的事件流数据库,使得处理和查询数据流变得更加简单和直观。 Confluent通过这些产品和服务简化了流数据的复杂性,帮助企业从实时数据中获得价值,并推动了实时分析和决策的新趋势。 原因 1、每家公司都通过这些关键技术和产品在其领域内建立了核心竞争力,推动了业务的增长和市场的认可。如kafka和MongoDB等都是各自领域的王 2、没有很重的负债,现金流比较健康,证明他们不会突然破产 3、我挑选的是中型公司,受长期利率影响较大,而未来美国一定会降息(虽然可能不会很多) 4、同样的逻辑,降息预期使钱从避险(七姐妹)流入真正好的公司。 5、根据高盛研究的一份报告,这几家公司都和ai高度相关。

丽江生态旅游元宇宙:探索虚拟世界的旅游新体验

在科技飞速发展的时代,元宇宙作为一个全新的概念逐渐融入我们的日常生活。而丽江,这个被誉为“人间仙境”的地方,也借助元宇宙技术,为游客带来了全新的生态旅游体验。近日,丽江生态旅游元宇宙项目正式启动,通过虚拟现实技术,将丽江的自然风光、民俗文化等元素完美呈现在虚拟世界中,让游客们能够随时随地畅游丽江,感受其独特的魅力。 **一、丽江生态旅游元宇宙的特点** 1. **沉浸式体验**:丽江生态旅游元宇宙利用先进的虚拟现实技术,为游客们营造出一种身临其境的感觉。无论是漫步在古城的石板路上,还是欣赏玉龙雪山的壮丽风光,都能让游客们仿佛置身其中,感受到丽江的独特魅力。 2. **互动性玩法**:在丽江生态旅游元宇宙中,游客们不仅可以欣赏美景,还能参与各种互动性玩法。比如,在虚拟环境中体验纳西族的传统文化、参加古城保护活动等,让游客们在游玩的同时,也能深入了解丽江的文化和历史。 3. **个性化定制**:丽江生态旅游元宇宙还提供了个性化定制服务。游客们可以根据自己的兴趣和需求,选择不同的游览路线和体验项目。无论是喜欢自然风光的游客,还是对民俗文化感兴趣的游客,都能在这里找到适合自己的玩法。 **二、丽江生态旅游元宇宙的意义** 1. **提升旅游体验**:丽江生态旅游元宇宙为游客们带来了全新的旅游体验。通过虚拟现实技术,游客们可以随时随地畅游丽江,感受其独特的魅力。这种沉浸式的体验方式,让游客们更加深入地了解丽江的文化和历史,增强了旅游的趣味性和意义。 2. **促进丽江旅游产业发展**:丽江生态旅游元宇宙项目的启动,为丽江旅游产业注入了新的活力。通过元宇宙技术,丽江的旅游资源得到了更广泛的传播和展示,吸引了更多游客前来观光旅游。同时,该项目也为丽江的旅游业提供了新的发展机遇和方向,推动了产业的转型升级。 3. **推动数字化发展**:丽江生态旅游元宇宙项目的成功实施,展示了数字化技术在旅游领域的广泛应用前景。通过元宇宙技术,可以实现旅游资源的数字化管理、虚拟化展示等功能,提高了旅游行业的运营效率和服务质量。同时,该项目也为其他领域的数字化发展提供了有益的借鉴和参考。 **三、结语** 丽江生态旅游元宇宙项目的启动,为游客们带来了全新的旅游体验方式。通过虚拟现实技术,游客们可以随时随地畅游丽江,感受其独特的魅力。同时,该项目也为丽江的旅游业注入了新的活力和机遇,推动了产业的数字化转型升级。相信在未来,随着技术的不断进步和应用的不断深入,丽江生态旅游元宇宙将为游客们带来更多惊喜和体验。 丽江生态旅游元宇宙ljstly.com

【爱上C++】vector模拟实现

文章目录 前言一:基本框架1.结构的定义2.构造函数①.详解 const T& val = T()②.为什么要多加一个int类的带参构造?】 3.析构函数4.size()和capacity()5.push_back尾插6.operator[]operator[]的返回类型为T&有以下几个原因: 二:迭代器的实现1.begin()和end()2.迭代器区间构造 三:reserve 引发的相关问题1.内部迭代器失效2.外部迭代器失效3.正确的实现_start 指针的作用 _start[i] 的含义 4.memcpy带来的问题 四:insert 引发的相关问题1.内部迭代器失效2.外部迭代器失效 五:erase 引发的相关问题修改后的执行过程 六:其他操作resize赋值运算符重载现代写法的思路为什么现代写法传参数时不能传引用?现代写法传参为什么不能传引用的具体原因: 七:完整代码 前言 上一节我们讲了vector的基本使用,现在我们讲解vector的模拟实现,其中有三大重难点: 1.vector是如何进行设计与封装的 2.迭代器失效问题 3.memcpy,memmove导致的浅拷贝问题 一:基本框架 1.结构的定义 #include <iostream> #include <assert.h> using namespace std; namespace myvector { template<class T> class vector { public: // Vector的迭代器是一个原生指针 typedef T* iterator; typedef const T* const_iterator; private: iterator _start; // 开始位置 iterator _finish; // 结束位置 iterator _endofstorage; // end of storage }; } 在 vector 类中,我们通常会使用_指针_来表示迭代器,因为指针天然支持指针算术运算和解引用操作,可以方便地遍历和访问元素。使用 typedef 定义迭代器类型可以使代码更加灵活和可维护。

单例模式->饿汉模式->懒汉模式->阻塞队列->模拟实现阻塞队列->生产者消费者模型

单例模式->是一种固定套路,类似于"棋谱",按照套路来,可以避免一些问题 单例模式的特点->能够保证在某个类中只存在一个实例,不会创建多个实例 饿汉模式(线程安全):最基础的单例模式,类加载的同时就会创建实例,是线程安全的 public class Singleton { // 在类加载时就完成了实例化,避免了线程同步的问题 private static Singleton instance = new Singleton(); private Singleton() {}// 私有构造函数,防止被外部实例化 public static Singleton getInstance() {// 获取单例对象的静态方法 return instance; } } 懒汉模式 (线程不安全):类加载的时候不会创建实例,第一次使用的时候才创建实例,线程不安全 public class SingleLaze { private static volatile SingleLaze instance = null; private SingleLaze() {} // 私有构造函数,防止外部实例化 public static SingleLaze getInstance() { if (instance == null) { //首次调用get方法instance==null才会创建实例 instance = new SingleLaze(); } return instance; } } 懒汉模式(线程安全版) 两个懒汉模式横向对比可以发现,修改后的加上了锁和双重if判定以及给instance加上lvolatile 加锁/解锁在懒汉模式只会发生在第一次创建实例的时候,后面使用的时候就不需要加锁外层的if是判断当前是否已有实例对象内层if是判定是否需要创建对象,由于第一个if语句和第二个if语句之间 因为synchronized发生的阻塞过程中,期间可能instance被其他线程创建了实例,所以双重判定在多线程/阻塞中很有必要volatile修饰instance确保多线程情况下的内存可见性和禁止指令重排序 public class SingleLaze { private static volatile SingleLaze instance = null; private SingleLaze() {} // 私有构造函数,防止外部实例化 public static SingleLaze getInstance() { if (instance == null) { // 第一次检查,避免已有实例对象,再次创建新的对象情况 synchronized (SingleLaze.

【AI大模型】李彦宏从“卷模型”到“卷应用”的深度解析:卷用户场景卷能给用户解决什么问题

文章目录 一、理解李彦宏的发言1.1 李彦宏的核心观点1.2 背景分析 二、技术发展:从辨别式到生成式2.1 辨别式AI技术2.2 生成式AI技术2.3 技术发展的挑战 三、“卷应用”:聚焦实际应用与价值3.1 应用为王3.2 技术落地的关键 四、“卷场景”:多元化应用场景的探索4.1 行业痛点与解决方案4.2 场景化应用的优势 五、未来展望:技术与应用的融合5.1 AI时代的新趋势5.2 为用户解决实际问题 六、AI应用案例分析6.1 医疗领域:早期疾病检测6.2 金融领域:智能投顾6.3 零售领域:个性化推荐 七、未来技术与应用的融合趋势7.1 跨领域合作7.2 边缘计算7.3 自适应系统 八、总结 在2024年7月4日于上海世博中心举办的世界人工智能大会上,百度创始人李彦宏的发言引起了广泛关注。他提到,“大家不要卷模型,要卷应用!”这句话看似简单,却深刻揭示了当前AI发展的关键问题和未来方向。在这篇博文中,我们将详细解读李彦宏的发言,并探讨技术发展、应用场景、未来趋势及其对用户的实际影响。 一、理解李彦宏的发言 1.1 李彦宏的核心观点 李彦宏指出,AI技术已经从辨别式转向生成式,然而技术本身并不是终极目的,其真正价值在于如何应用于实际场景,解决实际问题。他特别强调了避免“超级应用陷阱”的重要性,这一陷阱指的是过分追求用户日活跃量(DAU),而忽视了应用的实际效果和产业价值。 1.2 背景分析 当前,AI技术迅猛发展,特别是大模型的出现,如GPT-4等,在自然语言处理、图像生成等方面展现出强大的能力。然而,过度追求模型的复杂度和参数规模,可能会忽略了实际应用的价值。这也是李彦宏发言的核心要点:技术进步固然重要,但更关键的是如何将这些技术应用于实际场景,以解决实际问题。 二、技术发展:从辨别式到生成式 2.1 辨别式AI技术 辨别式AI技术主要用于分类和识别任务,比如图像分类、语音识别等。这类技术通常依赖于大量标注数据,通过监督学习进行训练。典型的辨别式模型包括卷积神经网络(CNN)、循环神经网络(RNN)等。 import tensorflow as tf from tensorflow.keras import layers, models # 构建一个简单的卷积神经网络模型 model = models.Sequential() model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1))) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.add(layers.MaxPooling2D((2, 2))) model.add(layers.Conv2D(64, (3, 3), activation='relu')) model.

【数据结构与算法】希尔排序:基于插入排序的高效排序算法

💓 博客主页:倔强的石头的CSDN主页 📝Gitee主页:倔强的石头的gitee主页 ⏩ 文章专栏:《数据结构与算法》 期待您的关注 ​ 目录 一、引言 二、基本原理 三、实现步骤 四、C语言实现 五、性能分析 1. 时间复杂度:近似为O(Nlog2N) 2. 空间复杂度:O(1) 3. 稳定性:不稳定的 六、优化 七、应用场景 一、引言 希尔排序(Shell Sort)是插入排序的一种更高效的改进版本,也称为缩小增量排序。 希尔排序由Donald Shell于1959年提出,并在其发表的论文“A high-speed sorting procedure”中详细描述了该算法。希尔排序的直接灵感来源于插入排序,但它在插入排序的基础上进行了显著的改进,旨在提高排序效率,特别是针对大规模数据集。 想要读懂希尔排序,最好先理解插入排序,参考下面这篇文章 【数据结构与算法】深入解析插入排序算法:原理、实现与优化-CSDN博客 二、基本原理 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次标准的直接插入排序。 这里的“基本有序”是指:待排序的数组元素值满足某个增量序列的“局部有序”,即对于某个变量gap,序列中所有距离为gap的元素之间是有序的。随着变量gap的逐渐减小,当gap减小到1时,整个序列恰好被“基本有序”,此时再对全体元素进行一次直接插入排序即可 三、实现步骤 1.外循环进行多轮预排序 选择一个变量序列: 这个序列是逐渐减小的,gap的值较大时,数据可以更快的前后变动,但不容易"基本有序";gap较小时数据前后变动较慢,但更接近"基本有序"。 通常可以选取gap = n/3, gap = gap/3, ...,直到gap= 1。 但是要注意,如果直接每次都/3,可能面临的情况就是最后一组gap的值跳过了1,比如n=8时,gap第一次等于2,第二次等于0,解决方法也很简单,gap每次不是/3,而是gap=gap/3+1,就可以让gap最后一次一定会减小到1 2.第二层循环,每一轮预排序中进行分组 按gap进行分组:根据当前的变量gap,将待排序的数组元素下标按gap分组,总共可以分成gap组。比如gap为3时,每一组元素的首元素分别是0,1,2 3.第三层循环,分组之后,控制组里数据执行插入排序 每一组的数据有n/gap个,下标为0,gap, 2gap, 3gap,...的元素分为一组;下标为1,gap+1,2gap+1,3gap+1……的元素分为一组…… 这一层循环一个需要注意的细节就是预防数组的越界:每一组分组数据的最后一个数据一般不会是数组的最后一个数据。每次选取的要插入的数据下标是end+gap,那么这个下标不能超过n-gap。比如数组有10个元素,gap为3,第一组数据最后一个数据的下标是9,要保证这一组数据访问到下标9之后,不再向后访问,因为下一次访问end为9,要插入的数据,9+gap的位置已经没有数据了。 4.第四层循环,实现插入排序的过程 每个数据向前扫描和移动,找到合适的位置后插入,直接在插入排序代码的基础上稍加修改即可 5.递减变量gap并重复上述分组排序过程: 每完成一轮按变量gap的分组排序后,将变量gap减小,然后重复分组排序过程,直到变量gap为1,此时整个数组恰好被分成一组,进行最后一次直接插入排序。 四、C语言实现 void ShellSort1(int* a, int n)//希尔排序升序 { int gap = n; while (gap > 1)//多组预排序,最后一组gap==1为直接插入排序 { gap = gap / 3 + 1; for (int i = 0; i <gap; i++)//控制分组的组数:gap组 { for (int j = i; j < n - gap; j += gap)//控制每组的插入元素个数:n/gap个 { int key = a[j+gap]; int end = j; while (end >= 0 && a[end] > key)//比较和移动元素 { a[end + gap] = a[end]; end -= gap; } a[end + gap] = key;//满足大小关系后插入到指定位置 } } } } void ShellSort2(int* a, int n)//希尔排序降序 { int gap = n; while (gap > 1)//多组预排序,最后一组gap==1为直接插入排序 { gap = gap / 3 + 1; for (int i = 0; i < gap; i++)//控制分组的组数:gap组 { for (int j = i; j < n - gap; j += gap)//控制每组的插入元素个数:n/gap个 { int key = a[j + gap]; int end = j; while (end >= 0 && a[end] < key)//比较和移动元素 { a[end + gap] = a[end]; end -= gap; } a[end + gap] = key;//满足大小关系后插入到指定位置 } } } } 五、性能分析 1.

无人驾驶的未来:AI如何重塑我们的出行世界

无人驾驶汽车,作为人工智能(AI)技术的集大成者,正以前所未有的速度改变着我们的出行方式。从机器学习到计算机视觉,再到人工智能生成内容(AIGC),AI技术的每一次进步都在为无人驾驶汽车的未来发展铺平道路。本文将深入探讨AI如何赋能无人驾驶,以及特斯拉与百度“萝卜快跑”如何在这个领域展开激烈的竞争与合作。 目录 引言:AI与无人驾驶的交汇点 AI赋能无人驾驶:技术核心与创新应用 特斯拉与百度“萝卜快跑”:竞争与合作的双重奏 当前挑战与未来展望 结语 引言:AI与无人驾驶的交汇点 无人驾驶汽车不仅仅是一种交通工具,它更是AI技术应用的一次革命。随着机器学习、计算机视觉等技术的快速发展,无人驾驶汽车正在逐步实现从科幻到现实的跨越。特斯拉和百度“萝卜快跑”作为这一领域的领军企业,它们的技术革新和市场策略,正在引领无人驾驶汽车走向一个全新的时代。 AI赋能无人驾驶:技术核心与创新应用 机器学习:智能驾驶的大脑 机器学习是AI赋能无人驾驶的关键技术之一。通过机器学习,无人驾驶汽车能够不断从行驶数据中学习,优化其决策算法,提高对复杂交通环境的适应能力。特斯拉的FSD系统就是机器学习技术在无人驾驶领域的典型应用。 数据驱动的智能进化 机器学习的核心在于数据。特斯拉通过收集全球范围内的行驶数据,训练其FSD系统,使其能够识别和预测各种交通场景。这种数据驱动的学习方法,使得无人驾驶汽车能够不断进化,适应不断变化的交通环境。 决策优化与风险评估 机器学习算法不仅能够识别交通标志和信号,还能够评估潜在的风险,做出最优的驾驶决策。这种决策优化能力,是无人驾驶汽车安全行驶的重要保障。 计算机视觉:智能驾驶的眼睛 计算机视觉技术赋予了无人驾驶汽车“看”的能力。通过摄像头和其他传感器,无人驾驶汽车能够实时感知周围环境,识别行人、车辆、交通信号等,为安全驾驶提供重要信息。百度“萝卜快跑”项目正是基于计算机视觉技术,实现了对复杂交通环境的有效感知。 环境感知与物体识别 计算机视觉技术使无人驾驶汽车能够识别和理解周围环境中的物体。这对于避免碰撞、遵守交通规则至关重要。 三维空间理解 除了识别物体,计算机视觉还能够理解物体在三维空间中的位置和运动状态。这对于无人驾驶汽车在复杂交通环境中的导航和避障至关重要。 AIGC:智能驾驶的内容创造者 人工智能生成内容(AIGC)技术为无人驾驶汽车提供了更加丰富的交互体验。通过AIGC,无人驾驶汽车能够根据用户的个性化需求,生成定制化的导航路线、音乐播放列表等内容,提升用户的出行体验。 通过一个个算法使体验更加安全,更加舒适,如路径规划算法: class Vehicle: def __init__(self, x, y): self.x = x # 车辆在X轴上的位置 self.y = y # 车辆在Y轴上的位置 def move(self, dx, dy): # 根据给定的偏移量移动车辆 self.x += dx self.y += dy class Obstacle: def __init__(self, x, y): self.x = x self.y = y def is_collision(veh, obs, safety_distance=1): # 检查车辆和障碍物是否发生碰撞 return ((veh.

顺序表<数据结构 C 版>

目录 线性表 顺序表 动态顺序表类型 初始化 销毁 打印 检查空间是否充足(扩容) 尾部插入 头部插入 尾部删除 头部删除 指定位置插入 指定位置删除 查找数据 线性表 线性表是n个相同特性的数据元素组成的有限序列,其是一种广泛运用的数据结构,常见的线性表有顺序表、栈、链表、队列等。 其在逻辑上是线性的,物理结构(存储结构)上不一定是线性的。 顺序表 顺序表就是线性表的一种,它在逻辑结构与物理结构上都是连续的,一般情况下它的底层就是数组,在数组基础上多了增删查改操作。 顺序表有静态顺序表和动态顺序表,我们常常采用动态顺序表,因为它的扩容方便、空间浪费更少。 动态顺序表类型 typedef int SeqDataType;//将动态顺表的存储数据的类型重命名,方便后期统一修改 //动态顺序表 typedef struct SeqList {//命名:Sequence List顺序表 SeqDataType* arr; int capacity;//动态顺序表的容量 int size;//动态顺序表的有效个数 }SL; 初始化 //初始化 void SLInit(SL* s) { s->arr = NULL; s->capacity = s->size = 0; } 销毁 //销毁 void SLDestory(SL* s) { if (!s->arr) {//等同于s->arr==NULL,判断要释放的空间是否是NULL,防止释放NULL perror("Destory Fail");//打印错误 exit(1); } free(s->arr);//释放动态开辟的内存 s->arr = NULL; s->capacity = s->size = 0; } 打印 打印操作方便我们检查错误。

Python酷库之旅-第三方库Pandas(023)

目录 一、用法精讲 58、pandas.isnull函数 58-1、语法 58-2、参数 58-3、功能 58-4、返回值 58-5、说明 58-6、用法 58-6-1、数据准备 58-6-2、代码示例 58-6-3、结果输出 59、pandas.notna函数 59-1、语法 59-2、参数 59-3、功能 59-4、返回值 59-5、说明 59-6、用法 59-6-1、数据准备 59-6-2、代码示例 59-6-3、结果输出 60、pandas.notnull函数 60-1、语法 60-2、参数 60-3、功能 60-4、返回值 60-5、说明 60-6、用法 60-6-1、数据准备 60-6-2、代码示例 60-6-3、结果输出 二、推荐阅读 1、Python筑基之旅 2、Python函数之旅 3、Python算法之旅 4、Python魔法之旅 5、博客个人主页 一、用法精讲 58、pandas.isnull函数 58-1、语法 # 58、pandas.isnull函数 pandas.isnull(obj) Detect missing values for an array-like object. This function takes a scalar or array-like object and indicates whether values are missing (NaN in numeric arrays, None or NaN in object arrays, NaT in datetimelike).

Hadoop数仓中常用端口详解:(第36天)

前言 在数仓(数据仓库)开发中,不同的组件和服务会使用不同的端口号进行通信。由于数仓的实现可能依赖于多种技术和框架(如Hadoop、Hive、HBase、Spark等),因此涉及的端口号也会有所不同。以下是一些数仓开发中常用端口号及其作用的概述,以及相关的操作指令建议。 常用端口号及其作用 1. Hadoop相关 端口号 组件/服务 作用 8020 NameNode RPC NameNode的远程过程调用(RPC)端口, 用于处理客户端和DataNode的请求。9000 NameNode HTTP(非高可用) NameNode的HTTP服务端口, 用于Web界面访问(如HDFS的Web UI)。注意,在高可用配置中,此端口可能不常用。50070 NameNode WebHDFS NameNode的WebHDFS端口, 通过HTTP协议提供对HDFS的访问。8088 YARN ResourceManager YARN集群的ResourceManager的Web UI端口, 用于监控和管理集群中的资源和任务。50010 DataNode 数据传输端口 用于DataNode与NameNode之间、DataNode与客户端之间的数据读写操作。 2. HDFS相关 端口号 组件/服务 作用50010 DataNode 数据传输端口 用于HDFS内部的数据传输,例如DataNode与NameNode之间、DataNode与客户端之间的数据读写操作。50020 DataNode IPC端口 DataNode的IPC(Inter-Process Communication)端口,用于接受来自NameNode或其他DataNode的命令和状态同步请求。注意,在某些Hadoop版本中,这个端口可能与其他功能合并或更改。50075 DataNode Web UI端口 DataNode的Web界面端口,通常用于查看DataNode的状态和报告。然而,需要注意的是,这个端口并不总是默认开启的,且其Web界面可能不如NameNode的Web界面那样详细。 在MapReduce(MR)环境中,特别是与Hadoop生态系统结合时,有几个常用的端口号。这些端口号主要与YARN(Yet Another Resource Negotiator)框架和MapReduce作业的执行情况相关。以下是一些常用的端口号及其作用: 3. YARN相关 8032:YARN ResourceManager的IPC(Inter-Process Communication)端口。ResourceManager是YARN的核心组件,负责集群资源的分配和管理。这个端口用于ResourceManager与其他YARN组件(如NodeManager)之间的内部通信。 8088:YARN ResourceManager的Web UI端口。通过这个端口,用户可以访问ResourceManager的Web界面,查看集群的状态、运行的应用程序以及相关的统计信息等。这是查看MapReduce作业执行情况的主要端口之一。 4. MapReduce相关 虽然MapReduce作业的执行情况主要通过YARN ResourceManager的Web UI(即8088端口)来查看,但MapReduce本身并不直接提供特定的Web UI端口。然而,MapReduce作业的日志和输出通常会存储在HDFS(Hadoop Distributed File System)上,因此与HDFS相关的端口(如50070或9870,取决于Hadoop的版本)也可能用于间接地查看MapReduce作业的输出和日志。 HDFS相关端口(间接相关) 50070(Hadoop 2.

【数据结构】栈和队列的深度探索,从实现到应用详解

💎所属专栏:数据结构与算法学习 💎 欢迎大家互三:2的n次方_ 🍁1. 栈的介绍 栈是一种后进先出的数据结构,栈中的元素只能从栈顶进行插入和删除操作,类似于叠盘子,最后放上去的盘子最先拿下来。 🍁2. 栈的基本操作 压栈(Push):将一个元素压入栈顶。出栈(Pop):移除并返回栈顶元素。栈顶元素(Peek):返回栈顶元素但不移除。判空(IsEmpty):检查栈是否为空。栈的大小(Size):返回栈中的元素个数。 栈的定义方法也是和ArrayList一样的,然后就是使用对象去调用栈的方法 public class Text { public static void main(String[] args) { Stack<Integer> stack1 = new Stack<>(); stack1.push(1); stack1.push(2); stack1.push(3); System.out.println(stack1.pop()); System.out.println(stack1.peek()); System.out.println(stack1.isEmpty()); System.out.println(stack1.size()); } } 🍁3. 栈的实现 首先,栈是通过数组实现的,就像之前实现的顺序表一样 public class MyStack { public int[] elem; public int usedSize; public MyStack() { this.elem = new int[10]; } } 接下来实现一些栈的基本操作 🍁3.1 push() 当1 2 3 4依次入栈时,如下图 入栈其实很简单,只需要把元素放进去,接着usedSize++就可以了,但是学习数据结构我们的思维要严谨,如果栈满了怎么办,所以还需要处理栈满的情况,栈满之后就扩容,扩容也是和之前的顺序表一样的,判断是否栈满了也很简单,只需要判断数组的长度和usedSize是否相等就可以了 public void push(int val) { if(isFull()) { this.

在Ubuntu 14.04上安装和保护phpMyAdmin的方法

前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家。点击跳转到网站。 简介 虽然许多用户需要像 MySQL 这样的数据库管理系统的功能,但他们可能不太习惯仅通过 MySQL 提示符与系统进行交互。 phpMyAdmin 的创建是为了让用户可以通过 Web 界面与 MySQL 进行交互。在本指南中,我们将讨论如何安装和保护 phpMyAdmin,以便您可以安全地在 Ubuntu 14.04 上使用它来管理数据库。 先决条件 在开始本指南之前,您需要完成一些基本步骤。 首先,我们假设您正在使用具有 sudo 特权的非根用户,就像在 Ubuntu 14.04 的初始服务器设置的步骤 1-4 中描述的那样。 我们还假设您已经在 Ubuntu 14.04 服务器上完成了 LAMP(Linux、Apache、MySQL 和 PHP)安装。如果尚未完成此步骤,您可以按照此指南在 Ubuntu 14.04 上安装 LAMP 堆栈。 完成这些步骤后,您就可以开始本指南了。 步骤一 — 安装 phpMyAdmin 要开始,我们可以简单地从默认的 Ubuntu 软件仓库中安装 phpMyAdmin。 我们可以通过更新本地软件包索引,然后使用 apt 软件包系统从系统中拉取文件并安装它们来完成这一点: sudo apt-get update sudo apt-get install phpmyadmin 这将要求您回答一些问题,以便正确配置您的安装。 对于服务器选择,选择 apache2。当询问是否使用 dbconfig-common 来设置数据库时选择 yes然后会提示您输入数据库管理员的密码然后会要求您选择并确认 phpMyAdmin 应用程序本身的密码 安装过程实际上将 phpMyAdmin Apache 配置文件添加到 /etc/apache2/conf-enabled/ 目录中,系统会自动读取该文件。

2.1 在Windows系统下载、安装、配置搭建Python开发环境——《跟老吕学Python》

2.1 在Windows系统下载、安装、配置搭建Python开发环境——《跟老吕学Python》 在Windows系统下载、安装、配置搭建 Python开发环境一、Python开发环境 的硬件要求二、下载Windows版 Python安装包1. 访问Python官网下载页2. 选择Python版本3. 下载Python安装程序 三、在Windows系统安装Python(全自动安装教程)1. 启动安装2. 安装进度3. 安装完成4. 查看版本5. 注意事项 四、安装Python(自定义安装教程,推荐新手使用)1. 启动安装2. 选择组件3. 高级选项4. 安装进度5. 安装完成6. 查看版本7. 验证安装8. 注意事项 五、在Windows系统配置Python环境变量1. 查找Python安装路径2. 配置系统环境变量2.1 打开环境变量设置2.2 添加Python到系统变量2.3 应用更改 3. 验证Python环境变量是否配置成功4. Python重要环境变量补充说明5. 注意事项 六、总结 在Windows系统下载、安装、配置搭建 Python开发环境 在Windows系统上搭建 Python开发环境 是编程初学者和专业开发人员常常需要面对的任务。Python作为一种流行的编程语言,广泛应用于数据分析、人工智能、Web开发等多个领域。以下是在Windows系统上下载、安装和配置 Python开发环境 的详细步骤。 一、Python开发环境 的硬件要求 在搭建 Python开发环境 时,硬件的选择对于开发者来说至关重要。 虽然Python是一种跨平台且相对轻量级的编程语言,但不同的项目和应用场景对硬件的要求也有所不同。以下是针对一般 Python开发环境 的计算机硬件要求: 处理器(CPU): 对于大多数Python开发任务,包括脚本编写、Web开发、数据处理等,一个中等性能的CPU(如Intel的i5或AMD的Ryzen 5)就已经足够了。然而,如果你正在开发需要高性能计算(如机器学习、深度学习、大数据分析等)的项目,那么一个更高性能的CPU(如Intel的i7或i9,AMD的Threadripper等)将更为理想。考虑到多线程和多核处理的能力,对于需要处理大量并行任务的项目,选择支持多核和多线程的CPU是非常重要的。 内存(RAM): 对于日常Python开发,8GB RAM通常是足够的。然而,如果你正在处理大型数据集、运行复杂的机器学习模型或进行其他内存密集型任务,那么更多的RAM(如16GB或更多)将更为理想。如果你计划使用虚拟机或Docker容器来隔离不同的开发环境,那么额外的RAM将更为必要。 存储设备(硬盘): 一个快速且容量足够的硬盘是Python开发的关键。虽然传统的机械硬盘(HDD)对于大多数开发任务来说已经足够,但如果你需要频繁地读取和写入大量数据,那么使用固态硬盘(SSD)将会大大提升开发效率。考虑到项目的长期存储和备份需求,选择具有足够容量的硬盘是非常重要的。 显卡(GPU): 对于大多数Python开发任务来说,显卡并不是必需的。然而,如果你正在开发涉及图形处理、游戏开发、机器学习(特别是深度学习)等需要高性能图形处理能力的项目,那么一个强大的GPU(如NVIDIA的GeForce RTX系列或AMD的Radeon RX系列)将是非常有用的。 显示器: 对于长时间进行Python开发的开发者来说,一个高质量的显示器是非常重要的。选择一款分辨率高、色彩表现准确、尺寸适中的显示器将有助于减少眼睛疲劳和提高工作效率。 其他: 考虑到开发过程中的舒适性和便利性,一些其他硬件如鼠标、键盘、耳机等也是非常重要的。选择一款符合人体工学设计、手感舒适、功能齐全的输入设备和一款能够隔绝噪音、提高专注度的耳机将大大提升开发体验。 Python开发环境 的硬件要求取决于你的具体需求和项目类型。在选择硬件时,请务必根据你的实际情况进行权衡和选择。 二、下载Windows版 Python安装包 在Windows系统上安装Python,首先需要从Python的官方网站或其他可信的下载源获取Python安装包。以下是详细的步骤说明:

[MySQL][表的约束][二][主键][自增长][唯一键][外键]详细讲解

目录 1.主键2.自增长1.是什么?2.索引 3.唯一键4.外键1.为什么?2.是什么?3.如何理解外键约束? 5.综合案例 -- 阅读 1.主键 主键:primary key用来唯一的约束该字段里面的数据,不能重复,不能为空,一张表中最多只能有一个 但不意味着一个表中的主键,只能添加给一列 一个主键可以被添加到一列,或者多列上 – 复合主键 示例:创建表的时候直接在字段上指定主键 mysql> create table t4 ( -> id int unsigned primary key comment '学号不能为空', -> name varchar(20) not null); mysql> desc t4; +-------+------------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+------------------+------+-----+---------+-------+ | id | int(10) unsigned | NO | PRI | NULL | | # key中pri表示该字段是主键 | name | varchar(20) | NO | | NULL | | +-------+------------------+------+-----+---------+-------+ 主键约束:主键对应的字段中不能重复,一旦重复,操作失败

基于springboot+vue+uniapp的高校就业招聘系统小程序

开发语言:Java框架:springboot+uniappJDK版本:JDK1.8服务器:tomcat7数据库:mysql 5.7(一定要5.7版本)数据库工具:Navicat11开发软件:eclipse/myeclipse/ideaMaven包:Maven3.3.9 系统展示 管理员登录 管理员功能界面 企业管理 用户管理 职位招聘管理 简历投递管理 简历管理 基础数据管理 论坛管理 公告信息管理 轮播图管理 系统首页 职位招聘 我的功能 摘要 系统以高校就业招聘系统为主题,利用不断发展和进步的网络技术,实现用户注册、登录、浏览公告信息、企业通知、简历投递、职位招聘、企业等信息,并进行简历、公告信息、企业通知、简历投递、职位招聘、职位收藏、职位留言、论坛信息的操作等。本论文介绍高校就业招聘系统软件的开发,主要是借助微信平台来完成的,框架使用的是Spring Boot框架,编程语言使用的是Java语言,数据库使用的是MySQL数据库。 研究背景 微信小程序可以将基于微信平台的用户和服务连起来,能够方便地通过微信进行访问和发布,并且拥有良好的应用体验。随着微信基础建设的完善(小程序、服务号、订阅号、视频号等),在微信内建立服务体系,逐步成为各行业的标配。 现在,各种各样的智能手机都出现了,各种各样的软件都是以手机为基础的,而在这么多的通讯软件中,小程序是最受欢迎的。这几年来,由于微信的迅猛发展带动着小程序的发展速度也发生了很大的变化,用户也越来越多了,现在随着智能手机的普及,每个人的手机上都安装了微信,这样子基本上我们每个人的手上就都有了小程序。“互联网+”高校就业招聘系统快速发展的当下,微信小程序以“用完即走”的设计理念在高校就业招聘系统拥有了越来越多的客户群。 关键技术 SpringBoot是一个全新开源的轻量级框架。基于Spring4.0设计,其不仅继承了Spring框架原来有的优秀特性,而且还通过简化配置文件来进一步简化了Spring应用的整个搭建以及开发过程。另外在原本的Spring中由于随着项目的扩大导入的jar包数量越来越大,随之出现了jar包版本之间的兼容性问题,而此时SpringBoot通过集成大量的框架使得依赖包的版本冲突,以及引用的不稳定性问题得到了很好的解决。 JS-SDK是对之前的 WeixinJSBrige 的一个包装,以及新能力的释放,并且由对内开放转为了对所有开发者开放,在很短的时间内获得了极大的关注。从数据监控来看,绝大部分在微信内传播的移动网页都使用到了相关的接口。 JS-SDK 解决了移动网页能力不足的问题,通过暴露微信的接口使得 微信小程序 开发者能够拥有更多的能力,然而在更多的能力之外,JS-SDK 的模式并没有解决使用移动网页遇到的体验不良的问题。用户在访问网页的时候,在浏览器开始显示之前都会有一个的白屏过程,在移动端,受限于设备性能和网络速度,白屏会更加明显。我们团队把很多技术精力放置在如何帮助平台上的微信小程序开发者解决这个问题。因此我们设计了一个 JS-SDK 的增强版本,其中有一个重要的功能,称之为“微信 微信小程序 资源离线存储”。 JAVA语言是目前软件市场上应用最广泛的语言开发程序。可以在多种平台上运用的,兼容性比较强,适应市面上大多数操作系统,不会出现乱码的现像,其扩展性和维护性都更好,具有分析问题和解决问题的能力,是面向过程的程序设计方便我们编写的代码更强壮。 Vue是一款流行的开源JavaScript框架,用于构建用户界面和单页面应用程序。Vue的核心库只关注视图层,易于上手并且可以与其他库或现有项目轻松整合。 MYSQL数据库运行速度快,安全性能也很高,而且对使用的平台没有任何的限制,所以被广泛应运到系统的开发中。MySQL是一个开源和多线程的关系管理数据库系统,MySQL是开放源代码的数据库,具有跨平台性。 B/S(浏览器/服务器)结构是目前主流的网络化的结构模式,它能够把系统核心功能集中在服务器上面,可以帮助系统开发人员简化操作,便于维护和使用。 系统分析 对系统的可行性分析以及对所有功能需求进行详细的分析,来查看该系统是否具有开发的可能。 系统设计 功能模块设计和数据库设计这两部分内容都有专门的表格和图片表示。 系统实现 管理员登录进入系统后台可以对个人中心、管理员管理、企业管理、用户管理、职位招聘管理、简历投递管理、企业通知管理、简历管理、基础数据管理、论坛管理、公告信息管理、轮播图信息等功能进行详细操作。企业登录进入系统后台可以对个人中心、职位招聘管理、简历投递管理、企业通知管理、论坛管理、公告信息管理等功能进行详细操作。系统首页是用户注册登录后进入的第一个界面,用户可以对公告信息、企业通知、简历投递、职位招聘、企业、我的等内容进行操作;点击“我的”进入我的管理页面,可以对修改密码,和对简历、公告信息、企业通知、简历投递、职位招聘、职位收藏、职位留言、论坛信息等进行详细操作。 系统测试 在系统测试中,测试作为一个重要环节起着至关重要的作用,它可以为系统质量管理提供可靠的依据。最后的测试与检查是必不可少的一个重要环节。在软件开发过程当中,每个人所需要做的事情是不同的,这就是常说的“人尽其才,物尽其用”。因此,软件维护人员必须做好自己的本职工作,加强管理。对于软件开发者来说,每项功能均要独立测试,测试阶段后再进行功能性软件开发。现在的软件开发过程中,将不同类型的软件进行集成和整合成为一个整体,从而实现软件复用。这种技术已经被广泛使用,并且取得了不错的效果。这样缩短了研发时间并且使一个早期测试就能检测出问题所在,从而合并后的软件在查找问题时不必快速修复或急速定位问题。 结论 本系统采用 Java技术、Spring Boot框架、微信小程序、MySQL数据库,实现了对服务器和小程序客户端数据的交互。本系统主要实现的功能有:实现个人信息修改,对个人中心、管理员管理、企业管理、用户管理、职位招聘管理、简历投递管理、企业通知管理、简历管理、基础数据管理、论坛管理、公告信息管理、轮播图信息等功能进行管理。本文首先从系统的基本原理、平台、技术等方面着手,然后对各个功能模块进行需求分析与设计,并利用模拟器实现各个功能接口。 (可运行源码+sql文件+文档)

记录些Spring+题集(1)

接口防刷机制 接口被刷指的是同一接口被频繁调用,可能是由于以下原因导致: 恶意攻击:攻击者利用自动化脚本或工具对接口进行大量请求,以消耗系统资源、拖慢系统响应速度或达到其他恶意目的。误操作或程序错误:某些情况下,程序错误或误操作可能导致接口被重复调用,例如循环调用或者定时任务配置错误。 Redis 实现接口防刷 Redis是高性能的键值存储系统,常用于缓存和分布式锁等场景。利用Redis可以有效地实现接口防刷功能: 计数器:利用Redis的计数器功能,每次接口被调用时增加计数器的值,设定一个时间窗口内的最大调用次数,超过该次数则拒绝请求。分布式锁:利用Redis的分布式锁功能,确保同一时间只有一个请求能够增加计数器的值,防止并发问题导致计数器失效。 拦截器实现接口防刷 在Spring Boot中,可以通过编写拦截器来实现接口防刷的功能: 编写拦截器:创建一个实现HandlerInterceptor接口的拦截器类,重写preHandle方法,在该方法中进行接口调用次数的检查,如果超过阈值则拦截请求。配置拦截器:在Spring Boot的配置类中通过addInterceptor方法将拦截器注册到拦截器链中,配置拦截器的拦截路径和排除路径。 分布式ID生成策略 构建分布式系统时,如何对数据进行唯一标识也是一个至关重要的设计。不仅要符合B-tree数据结构以维持查询性能,还要考虑唯一标识的连续性会不会影响系统安全性。在分库分表的情况下,还要避免唯一标识重复且高效等等需要考虑的点。 1、UUID UUID(Universally Unique Identifier)是基于当前时间、计数器和硬件标识(通常为无线网卡的MAC地址)等数据计算生成的。UUID完全可以满足分布式唯一标识,但是在实际应用过程中一般不采用,有几个原因:(如果UUID作为数据库主键,在InnoDB引擎下,UUID的无序性可能会引起数据位置频繁变动,严重影响性能。) 存储成本高:UUID太长,16字节128位,以36长度的字符串表示,很多场景不适用。信息不安全:基于MAC地址生成的UUID算法会暴露MAC地址,曾经梅丽莎病毒的制造者就是根据UUID寻找的。不符合MySQL主键要求:MySQL官方有明确的建议,主键要尽量越短越好,因为太长对MySQL索引不利。 2、数据库自增ID 利用MySQL自增的ID,可以达到数据唯一标识。但是分库分表后不能保证整体的ID唯一。为了避免这种情况,有以下两种方式可以解决该问题。 全局主键表 创建全局主键表维护唯一标识,作为ID的输出源可以保证整体ID的唯一。 ID自增步长设置 通过设置MySQL不同实例的主键自增步长为不同值,让分布在不同实例的表数据ID做到不重复,从而保证整体的唯一。但是这种方式的扩展性会是一个非常大的问题。 3、号段模式 号段模式是当下分布式ID生成器的主流实现方式之一。其原理如下: 号段模式每次从数据库取出一个号段范围,加载到服务内存中。避免每次生成ID都去访问数据库。当号段ID用完,再次向数据库申请新号段,对max_id字段做一次update操作,新的号段范围是(max_id ,max_id +step]。由于多业务端可能同时操作,所以采用版本号version乐观锁方式更新。 这种分布式ID生成方式不强依赖于数据库,不会频繁的访问数据库,对数据库的压力小很多。但同样也会存在一些缺点,比如:服务器重启,单点故障会造成ID不连续。 4、Redis INCR 作为共享内存,可以通过Redis的INCR命令来生成全局唯一ID。Redis也有对应的缺点:ID 生成的持久化问题,如果Redis宕机了怎么进行恢复是开发人员需要考虑的。 5、雪花算法 Snowflake,雪花算法是由Twitter开源的分布式ID生成算法,以划分命名空间的方式将64bit位分割成了多个部分,每个部分都有具体的不同含义,在Java中64Bit位的整数是Long类型,所以在Java中Snowflake算法生成的ID就是long来存储的。具体如下: 雪花算法强依赖机器时钟,如果机器上时钟回拨,会导致重复。通常通过记录最后使用时间处理该问题。 6、美团(Leaf) 美团点评分布式ID生成系统。支持号段模式和snowflake算法模式,可以切换使用。 开源项目链接:https://github.com/Meituan-Dianping/Leaf Leaf详细介绍:https://tech.meituan.com/2017/04/21/mt-leaf.html 7、百度(UidGenerator) UidGenerator是基于Snowflake算法的。克服了雪花算法的并发限制,单个实例的QPS能超过6000000。需要的环境:JDK8+,MySQL(用于分配WorkerId)。 源码地址:https://github.com/baidu/uid-generator 中文文档地址:https://github.com/baidu/uid-generator/blob/master/README.zh_cn.md 8、滴滴(TinyID) Tinyid是滴滴基于美团(Leaf)的号段模式基础上升级而来,不仅支持了数据库多主节点模式,还提供了tinyid-client客户端的接入方式,使用起来更加方便。 开源项目链接:https://github.com/didi/tinyid 总结比较 优点缺点UUID代码实现简单、没有网络开销,性能好占用空间大、无序数据库自增ID利用数据库系统的功能实现,成本小、ID自增有序并发性能受Mysql限制、强依赖DB,当DB异常时整个系统不可用,致命Redis INCR性能优于数据库、ID有序解决单点问题带来的数据一致性等问题使得复杂度提高雪花算法不依赖数据库等第三方系统,性能也是非高、可以根据自身业务特性分配bit位,非常灵活强依赖机器时钟,如果机器上时钟回拨,会导致发号重复或者服务会处于不可用状态。号段模式数据库的压力小单点故障ID不连续Leaf、Uidgenerator、TinyID高性能、高可用、接入简单依赖第三方组件如ZooKeeper、Mysql

C++中链表的底层迭代器实现

大家都知道在C++的学习中迭代器是必不可少的,今天我们学习的是C++中的链表的底层迭代器的实现,首先我们应该先知道链表的底层迭代器和顺序表的底层迭代器在实现上有什么区别,为什么顺序表的底层迭代器更加容易实现,而链表的底层迭代器不容易实现,接下来小编再来告诉大家如何来实现链表的底层迭代器,学完今天这篇我相信大家对C++中的迭代器一定会有一个更加深刻的认识!大家先看今天学习的内容: 一、顺序表和链表的底层迭代器的区别 为了知道它们两个的区别,先得告诉大家顺序表的底层迭代器是如何实现的,首先大家先得明白顺序表私有成员都有什么,好方便大家来理解它们的底层迭代器是如何实现的,请看下图顺序表的私有成员变量: private: iterator _start; iterator _finish; iterator _end_of_storage; 如图就是顺序表的私有成员变量 第一个 _start 是记录顺序表的起始位置的指针类型是 T* _finish记录的是顺序表内末尾元素的下一个位置的指针类型是T*,_end_of_storage记录的是顺序表的目前的所有容量的下一个位置类型也是T*。 在明白了顺序表的私有成员变量的意义,并且顺序表的储存是连续的空间有点类似于数组的数据储存,所以大家也应该明白了顺序表的底层迭代器是如何实现的了吧,如果不懂请看下图操作及注释,如下图: 但是由于链表的物理结构不是连续的,所以想顺序表一样的底层迭代器实现方法是行不通的,这也是为什么在底层实现链表的迭代器中,不能通过给迭代器++来做到迭代器指向下一个元素的地址,因为链表的数据在空间中分布式随意的。那该如何去设计链表的底层迭代器呢,请大家继续往下看。 二、链表的底层迭代器该如何实现 首先先请大家看一下链表中的数据是如何分布的,如下图: 如图,可见链表中的数据是随意分布的,但是我们仍然可以用前一个节点找到下一个节点,但为什么这样子不行,不算迭代器呢,因为在C++中迭代器的定义就是通过 ++ 来找到下一个元素,接通过 * 号来拿到他这个位置的数据,这才是迭代器的规定,如下段代码的遍历效果: 如上链表的分布图,虽然我们可以拿到下一个节点的位置和这个节点的数据,但我们不是通过 ++ 和 * 来实现的,所以通过这样的方式做出的迭代器是不对的。那我们该如何实现呢,小编新学了一个方法,就是把迭代器底层封装成一个类,让它内部进项运算符重载来达到 ++ 实现像迭代器一样遍历的过程,* 实现像迭代器一样拿出数据的过程,那么该如何实现呢,请大家继续往下看。 三、链表底层迭代器的实现 上面说到把迭代器封装成一个类,然后用运算符重载来达到 ++ 和 * 的过程,把它彻底改变为一个正规的迭代器,现在大家就和我一起实现这个迭代器的类: 1、首先大家要明白链表(带头双向循环链表)的结构,如下代码: template<class T> // 这里用结构体是因为ListNode中的每个成员都应该可以访问 没有私有成员 // 也可以使用友元来解决这个问题 struct ListNode { T _data; ListNode* _next; ListNode* _prev; ListNode(const T& data = T()) :_next(nullptr) ,_prev(nullptr) , _data(data) {} }; template<class T> class list { public: typedef ListNode<T> Node; private: Node* _head; }; 如上图代码,在这里我们已经知道下一步需要把链表独特的遍历方式(用前一个指针找到后一个指针)用运算符重载的改为 ++ 和 * 来实现遍历和拿到数据,保证它和迭代器的实现和用法一模一样。那该如何实现这个类呢。

数据结构之通过“ 队列 ”实现的“ 栈 ”功能。

🌹个人主页🌹:喜欢草莓熊的bear 🌹专栏🌹:数据结构 前言 本节内容是利用“ 队列 ”先进先出的特点 实现 “ 栈 ” 先进后出。 一、题目 1.1 题目描述: 请你仅使用两个队列实现一个后入先出(LIFO)的栈,并支持普通栈的全部四种操作(push、top、pop 和 empty)。 实现 MyStack 类: void push(int x) 将元素 x 压入栈顶。int pop() 移除并返回栈顶元素。int top() 返回栈顶元素。boolean empty() 如果栈是空的,返回 true ;否则,返回 false 。 注意: 你只能使用队列的标准操作 —— 也就是 push to back、peek/pop from front、size 和 is empty 这些操作。你所使用的语言也许不支持队列。 你可以使用 list (列表)或者 deque(双端队列)来模拟一个队列 , 只要是标准的队列操作即可。 示例: 输入: ["MyStack", "push", "push", "top", "pop", "empty"] [[], [1], [2], [], [], []] 输出: [null, null, null, 2, 2, false] 解释: MyStack myStack = new MyStack(); myStack.