【C++】关联存储结构容器-set(集合)详解

目录

一、基本概念

二、内部实现

三、常用操作

3.1 构造函数

3.2 插入操作

3.3 删除操作

3.4 查找操作

3.5 访问元素

3.6 容量操作

3.7 交换操作

四、特性

五、应用场景

结语


一、基本概念

set是C++标准模板库(STL)中的一种关联容器,它主要用于存储唯一且有序的元素。set容器不允许元素重复,并且会自动对元素进行排序。set的内部实现通常基于红黑树(一种自平衡二叉搜索树),这使得set的插入、删除和查找操作的时间复杂度都是O(log n)。


二、内部实现

set容器的内部实现基于红黑树,红黑树是一种自平衡的二叉搜索树,具有以下特性:

  • 每个节点是红色或黑色。
  • 根节点是黑色。
  • 每个叶子节点(NIL节点,空节点)是黑色。
  • 如果一个节点是红色的,则它的两个子节点都是黑色的。
  • 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。

这些特性确保了红黑树在插入和删除操作后能够重新平衡,从而保持树的高度在对数级别,进而保证了set容器的高效性。


三、常用操作

set容器提供了丰富的成员函数来支持各种操作。


3.1 构造函数

set容器提供了多种构造函数,可以根据实际需求选择合适的构造函数来创建set对象。常见的构造函数包括:

  • 默认构造函数:创建一个空的set对象。
#include <iostream>
#include <set>

int main() {
    std::set<int> emptySet; // 使用默认构造函数创建一个空的set对象

    // 输出set的大小以验证其为空
    std::cout << "Size of emptySet: " << emptySet.size() << std::endl; // 输出应为0

    return 0;
}
  • 初始化列表构造函数:通过初始化列表来创建set对象,并初始化元素。
#include <iostream>
#include <set>

int main() {
    std::set<int> initListSet = {1, 2, 3, 4, 5}; // 使用初始化列表构造函数创建并初始化set对象

    // 遍历并输出set中的元素
    for (int num : initListSet) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}
  • 复制构造函数:创建一个新的set对象,它是现有set对象的副本。
#include <iostream>
#include <set>

int main() {
    std::set<int> originalSet = {1, 2, 3}; // 原始set对象
    std::set<int> copySet(originalSet); // 使用复制构造函数创建新的set对象作为副本

    // 验证复制是否成功
    std::cout << "Original set: ";
    for (int num : originalSet) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    std::cout << "Copied set: ";
    for (int num : copySet) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}
  • 迭代器范围构造函数:通过一个已有的迭代器范围(如另一个容器的子范围)来构造set对象。
#include <iostream>
#include <set>
#include <vector>

int main() {
    std::vector<int> vec = {10, 20, 30, 40, 50}; // 原始vector容器
    std::set<int> iteratorRangeSet(vec.begin(), vec.end()); // 使用迭代器范围构造函数创建set对象

    // 遍历并输出set中的元素
    for (int num : iteratorRangeSet) {
        std::cout << num << " ";
    }
    std::cout << std::endl;

    return 0;
}
  • 指定排序方式的构造函数:当构造自定义类型的容器时,可以指定一个自定义的比较函数来确定元素的排序方式。 
#include <iostream>
#include <set>
#include <string>

// 自定义比较函数,用于按字符串长度排序
struct CompareByLength {
    bool operator()(const std::string& lhs, const std::string& rhs) const {
        return lhs.length() < rhs.length();
    }
};

int main() {
    std::set<std::string, CompareByLength> customSortSet = {"apple", "banana", "cherry", "date"}; // 使用自定义比较函数创建set对象

    // 遍历并输出set中的元素
    for (const std::string& str : customSortSet) {
        std::cout << str << " ";
    }
    std::cout << std::endl;

    return 0;
}

3.2 插入操作

set容器提供了多种插入元素的方法。

  • insert方法:插入单个元素或插入一个范围内的元素。如果插入的元素已经存在于set中,则插入操作会被忽略。
#include <iostream>
#include <set>

int main() {
    std::set<int> mySet;

    // 插入单个元素
    auto result1 = mySet.insert(5);
    if (result1.second) {
        std::cout << "Inserted 5 successfully." << std::endl;
    } else {
        std::cout << "5 already exists in the set." << std::endl;
    }

    // 尝试插入已存在的元素
    auto result2 = mySet.insert(5);
    if (result2.second) {
        std::cout << "Inserted 5 successfully." << std::endl;
    } else {
        std::cout << "5 already exists in the set." << std::endl;
    }

    // 插入一个范围内的元素(例如,从数组)
    int arr[] = {1, 2, 3, 4, 5};
    mySet.insert(arr, arr + 5);

    // 打印 set 中的元素
    std::cout << "Elements in the set: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

上述代码输出:

 

  • emplace方法:直接在容器中构造元素,避免临时对象的创建和复制,性能更优。
#include <iostream>
#include <set>
#include <string>

class Person {
public:
    std::string name;
    int age;

    Person(std::string name, int age){
        this->name = name;
        this->age = age;
    }

    // 需要定义 < 运算符,以便 set 可以对 Person 进行排序
    bool operator<(const Person& other) const {
        if (name != other.name) {
            return name < other.name;
        }
        return age < other.age;
    }
};

int main() {
    std::set<Person> mySet;

    // 使用 emplace 插入单个元素
    mySet.emplace("Alice", 30);
    mySet.emplace("Bob", 25);

    // 尝试插入已存在的元素(根据我们的定义,name 和 age 都相同才算相同元素)
    auto result = mySet.emplace("Alice", 30);
    if (result.second) {
        std::cout << "Inserted Alice, 30 successfully." << std::endl;
    } else {
        std::cout << "Alice, 30 already exists in the set." << std::endl;
    }

    // 打印 set 中的元素
    std::cout << "Elements in the set: ";
    for (const auto& person : mySet) {
        std::cout << person.name << ", " << person.age << " ";
    }
    std::cout << std::endl;

    return 0;
}

上述代码输出:

 


3.3 删除操作

set容器提供了多种删除元素的方法。

  • erase方法:删除指定元素、删除指定位置的元素或删除指定范围内的元素。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并添加一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    // 打印原始set
    std::cout << "Original set: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 删除指定元素(例如,删除元素3)
    mySet.erase(3);
    std::cout << "After erasing element 3: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 插入元素以便演示删除指定位置的元素
    mySet.insert(3);
    mySet.insert(6);
    
    // 打印当前set
    std::cout << "Current set before erasing position: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 删除指定位置的元素(例如,删除第一个元素,即1)
    auto it = mySet.begin();
    mySet.erase(it);
    std::cout << "After erasing first element: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 删除指定范围内的元素(例如,删除从3到5的元素)
    it = mySet.find(3); // 找到3的迭代器
    if (it != mySet.end()) {
        auto nextIt = std::next(it); // 指向下一个元素(4)的迭代器
        auto lastIt = mySet.find(5); // 找到5的迭代器,若不存在则返回end()
        if (lastIt != mySet.end()) {
            mySet.erase(nextIt, std::next(lastIt)); // 注意std::next(lastIt)是为了包含5但不越界
        } else {
            mySet.erase(nextIt, mySet.end()); // 若5不存在,删除从4到末尾的所有元素
        }
    }
    std::cout << "After erasing range [3, 5]: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

上述代码输出:

 

  • clear方法:清空set容器中的所有元素。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并添加一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    // 打印原始set
    std::cout << "Original set: ";
    for (const auto& elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 清空set容器中的所有元素
    mySet.clear();
    std::cout << "After clearing the set: ";
    if (mySet.empty()) {
        std::cout << "The set is empty.";
    } else {
        for (const auto& elem : mySet) {
            std::cout << elem << " ";
        }
    }
    std::cout << std::endl;

    return 0;
}

上述代码输出:


3.4 查找操作

set容器提供了高效的查找操作。

  • find方法:查找指定元素的迭代器。如果找到该元素,则返回指向该元素的迭代器;否则返回end()迭代器。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并插入一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    // 使用find方法查找元素
    int valueToFind = 3;
    auto it = mySet.find(valueToFind);
    if (it != mySet.end()) {
        std::cout << "Found " << valueToFind << " at position: " << *it << std::endl;
    } else {
        std::cout << valueToFind << " not found in the set." << std::endl;
    }
}
  • count方法:返回容器中给定值的数量(对于set容器,一般返回1或0)。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并插入一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    // 使用count方法计算元素数量
    std::cout << "Count of " << valueToFind << ": " << mySet.count(valueToFind) << std::endl;

    return 0;
}
  • lower_bound和upper_bound方法:分别返回指向大于或等于给定元素的第一个元素的迭代器和指向大于给定元素的第一个元素的迭代器。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并插入一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    // 使用lower_bound和upper_bound方法
    int lowerBoundValue = 3;
    int upperBoundValue = 4;
    auto lowerIt = mySet.lower_bound(lowerBoundValue);
    auto upperIt = mySet.upper_bound(upperBoundValue);
    // -1代表未找到
    std::cout << "Lower bound of " << lowerBoundValue << ": " 
          << (lowerIt != mySet.end() ? *lowerIt : -1) << std::endl;
    std::cout << "Upper bound of " << upperBoundValue << ": " 
          << (upperIt != mySet.end() ? *upperIt : -1) << std::endl;

    return 0;
}

上述代码输出:

 

  • equal_range方法:返回一个pair,表示给定元素在set容器中的范围(前闭后开)。
#include <iostream>
#include <set>

int main() {
    // 创建一个set容器并插入一些元素
    std::set<int> mySet = {1, 2, 3, 4, 5};

    int valueToFind = 3;

    // 使用equal_range方法
    auto range = mySet.equal_range(valueToFind);
    // -1代表未找到
    std::cout << "Equal range of " << valueToFind << ": [" 
              << (range.first != mySet.end() ? *range.first : -1) << ", " 
              << (range.second != mySet.end() ? *range.second : -1) << ")" << std::endl;

    return 0;
}

上述代码输出: 

 


3.5 访问元素

set容器提供了通过迭代器和成员函数来访问元素的方法。由于set容器中的元素是唯一的且有序的,因此不能直接通过下标来访问元素。但可以通过迭代器来遍历set容器中的元素。在C++11 及更高版本中,也可以使用范围 for 循环来遍历 std::set 容器中的元素。

#include <iostream>
#include <set>

int main() {
    // 创建一个 std::set 容器,并插入一些整数元素
    std::set<int> mySet = {1, 3, 5, 7, 9, 2, 4, 6, 8, 0};

    // 使用迭代器来遍历 std::set 容器中的元素
    for (std::set<int>::iterator it = mySet.begin(); it != mySet.end(); ++it) {
        std::cout << *it << " ";
    }
    std::cout << std::endl;

    // 也可以使用范围 for 循环来遍历 std::set 容器中的元素(C++11 及更高版本)
    for (int elem : mySet) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

3.6 容量操作

set容器提供了一些容量相关的操作来管理和查询容器的大小。

  • empty方法:判断容器是否为空。
#include <iostream>
#include <set>

int main() {
    // 创建一个空的 std::set 容器
    std::set<int> mySet;

    // 使用 empty 方法判断容器是否为空
    if (mySet.empty()) {
        std::cout << "The set is empty." << std::endl;
    } else {
        std::cout << "The set is not empty." << std::endl;
    }

    return 0;
}
  • size方法:返回容器当前元素的数量。
#include <iostream>
#include <set>

int main() {
    // 创建一个空的 std::set 容器
    std::set<int> mySet;

    // 向 set 容器中添加一些元素
    mySet.insert(1);
    mySet.insert(2);
    mySet.insert(3);

    // 使用 size 方法返回容器当前元素的数量
    std::cout << "The set has " << mySet.size() << " elements." << std::endl;

    return 0;
}
  • max_size方法:返回set容器能够容纳元素的最大值(虽然set容器没有容量的概念,但这个方法可以返回一个理论上的最大值)。
#include <iostream>
#include <set>

int main() {
    // 创建一个空的 std::set 容器
    std::set<int> mySet;

    // 使用 max_size 方法返回 set 容器能够容纳元素的最大值
    // 注意:这个值通常非常大,表示理论上可以容纳的元素数量,而不是实际容量限制
    std::cout << "The maximum number of elements the set can hold is " << mySet.max_size() << "." << std::endl;

    return 0;
}

上述代码输出:

3.7 交换操作

set容器提供了swap方法来交换两个set容器的内容。

#include <iostream>
#include <set>

int main() {
    // 创建两个 std::set 容器,并插入一些元素
    std::set<int> set1 = {1, 2, 3, 4, 5};
    std::set<int> set2 = {6, 7, 8, 9, 10};

    // 打印交换前的容器内容
    std::cout << "Before swap:" << std::endl;
    std::cout << "set1: ";
    for (int elem : set1) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    std::cout << "set2: ";
    for (int elem : set2) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    // 使用 swap 方法交换两个容器的内容
    set1.swap(set2);

    // 打印交换后的容器内容
    std::cout << "After swap:" << std::endl;
    std::cout << "set1: ";
    for (int elem : set1) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    std::cout << "set2: ";
    for (int elem : set2) {
        std::cout << elem << " ";
    }
    std::cout << std::endl;

    return 0;
}

上述代码输出:

 


四、特性

  1. 自动排序:set容器中的元素会自动根据其值进行排序。你不需要像使用数组或链表那样手动排序。

  2. 唯一性:set容器只存储唯一的元素,这样可以确保数据的一致性,不会出现重复的数据。

  3. 高效的查找操作:由于set实现为红黑树,其查找、插入和删除操作的平均时间复杂度为O(log n)。

  4. 标准容器:set是C++标准库的一部分,因此与其它标准库组件有良好的兼容性。

  5. 值的不可变性:一旦将一个元素插入到set中,你就不能更改该元素的值(尽管可以通过删除旧元素并插入新元素来间接实现更改)。

  6. 内存使用:由于set需要为每个元素分配内存并维护一棵红黑树,所以它的内存使用可能会比其它容器(如数组或向量)更高。

  7. 迭代器的稳定性:set的迭代器在删除元素后可能会失效。如果你在迭代过程中删除元素,可能会导致未定义的行为。为了安全地删除元素,你可以先保存要删除元素的迭代器,然后在迭代完成后再进行删除。


五、应用场景

  1. 去重:set容器自动去重的特性使其成为处理去重问题的理想选择。

  2. 集合运算:set支持并集、交集和差集等集合运算,适用于需要进行集合操作的场景。

  3. 有序存储:set中的元素自动按顺序排列,适合需要有序存储的场景。

  4. 查找:set的查找操作时间复杂度为O(log n),适用于需要快速查找的场景。

结语

在C++的标准模板库(STL)中,set容器作为一种关联存储结构,以其独特的性质和高效的性能,在数据管理和处理中扮演着重要角色。通过本文深入学习和掌握set容器的使用方法和技巧,程序员可以更好地应对各种复杂的编程挑战,提升编程能力和水平。希望本文的介绍能够对你理解和使用set容器有所帮助。

如需更多信息,建议查阅C++参考手册中的set: 

https://cppreference.cn/w/cpp/container/set 

 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ssm-day03 aoptx

AOP AOP指的是面向对象思想编程问题的一些补充和完善 soutp、soutv 解耦通俗理解就是把非核心代码剥出来&#xff0c;减少对业务功能代码的影响 设计模式是解决某些特定问题的最佳解决方案&#xff0c;后面一点要记得学这个&#xff01;&#xff01;&#xff01; cxk唱跳哈…

谷粒商城—分布式高级①.md

1. ELASTICSEARCH 1、安装elastic search dokcer中安装elastic search (1)下载ealastic search和kibana docker pull elasticsearch:7.6.2 docker pull kibana:7.6.2(2)配置 mkdir -p /mydata/elasticsearch/config mkdir -p /mydata/elasticsearch/data echo "h…

数据仓库的性能问题及解决之道

随着数据量不断增长和业务复杂度逐渐攀升&#xff0c;数据处理效率面临巨大挑战。最典型的表现是面向分析型场景的数据仓库性能问题越来越突出&#xff0c;压力大、性能低&#xff0c;查询时间长甚至查不出来&#xff0c;跑批跑不完造成生产事故等问题时有发生。当数据仓库出现…

云和恩墨 zCloud 与华为云 GaussDB 完成兼容性互认证

近日&#xff0c;云和恩墨&#xff08;北京&#xff09;信息技术有限公司&#xff08;以下简称&#xff1a;云和恩墨&#xff09;的多元数据库智能管理平台 zCloud 与华为云计算技术有限公司&#xff08;以下简称&#xff1a;华为云&#xff09;的 GaussDB 数据库完成了兼容性互…

分布式专题(4)之MongoDB快速实战与基本原理

一、MongoDB介绍 1.1 什么是MongoDB MongoDB是一个文档数据库(以JSON为数据模型)&#xff0c;由C语言编写&#xff0c;旨在为WEB应用提供可扩展的高性能存储解决方案。 MongoDB是一个介于关系数据库和非关系数据库之间的产品&#xff0c;是非关系数据库当中功能最丰富&#xf…

03篇--二值化与自适应二值化

二值化 定义 何为二值化&#xff1f;顾名思义&#xff0c;就是将图像中的像素值改为只有两种值&#xff0c;黑与白。此为二值化。 二值化操作的图像只能是灰度图&#xff0c;意思就是二值化也是一个二维数组&#xff0c;它与灰度图都属于单信道&#xff0c;仅能表示一种色调…

Linux下redis环境的搭建

1.redis的下载 redis官网下载redis的linux压缩包&#xff0c;官网地址:Redis下载 网盘链接&#xff1a; 通过网盘分享的文件&#xff1a;redis-5.0.4.tar.gz 链接: https://pan.baidu.com/s/1cz3ifYrDcHWZXmT1fNzBrQ?pwdehgj 提取码: ehgj 2.redis安装与配置 将包上传到 /…

印闪网络:阿里云数据库MongoDB版助力金融科技出海企业降本增效

客户背景 上海印闪网络科技有限公司&#xff0c;于2017年1月成立&#xff0c;投资方包括红杉资本等多家国际知名风投公司。公司业务聚焦东南亚普惠金融&#xff0c;常年稳居行业头部。创始团队来自腾讯&#xff0c;中国团队主要由运营、风控及产研人员组成&#xff0c;核心成员…

【有啥问啥】大语言模型Prompt中的“System指令”:深入剖析与误区澄清

大语言模型Prompt中的“System指令”&#xff1a;深入剖析与误区澄清 引言 在与大语言模型&#xff08;LLM&#xff09;交互时&#xff0c;“prompt”&#xff08;提示符&#xff09;这一概念已不再陌生。Prompt是引导模型生成特定类型文本的关键输入&#xff0c;决定了模型的…

【解决】Vue配置了端口号 发布项目仍会改变

1 梗概 这里记录Vue配置了端口号&#xff0c;npm run serve 发布运行仍会选择其他端口&#xff0c;一般是配置的端口号1 2 解决方案 网上有些教程说是由于 portfonder 版本问题&#xff0c;需要降低版本&#xff0c;可能这个的确是个解决方案。 还有说在package.json 中配置 &q…

uniapp-在windows上IOS真机运行(含开发证书申请流程)

前期准备 1、Itunes [Windows 32位 iTunes]下载地址、所有版本的iTunes下载地址 [Windows 64位 iTunes]下载地址、所有版本的iTunes下载地址 2、爱思助手 https://www.i4.cn/ 3、typeC转Usb接口 (物理意义的设备接口&#xff09; 4、Mac电脑&#xff08;用来生成证书&am…

网络层分析

网络访问层仍受到传输介质的性质和相关适配器的设备驱动程序的影响很大。网络层与网络适配器的硬件性质几乎是完全分离的。为什么是几乎呢&#xff1f;该层不仅负责发送和接受网络数据&#xff0c;还负责在彼此不直接连接的系统之间转发和路由分组。查找最佳路由并选择适当的网…

罗技键鼠更换新台式机无蓝牙通过接收器安装

优联驱动下载&#xff1a; http://support.logitech.com.cn/zh_cn/software/unifying &#xff08;下载安装后按照步骤一步步操作&#xff0c;匹配后即可使用&#xff09; 向京东客服反馈后提供的驱动下载安装连接 有问题欢迎评论沟通~

《Keras3 minist 手写数字AI模型训练22秒精度达到:0.97》

《Keras3 minist 手写数字AI模型训练22秒精度达到&#xff1a;0.97》 一、修改源码加上如下两条代码二、源码修改如下三、Keras3 minist 训练22秒结束&#xff0c;训练过程截图四、Keras3 minist 源码截图 一、修改源码加上如下两条代码 import os os.environ["KERAS_BAC…

装饰模式的理解和实践

在软件设计中&#xff0c;设计模式提供了一种可复用的解决方案&#xff0c;用于解决常见的设计问题。装饰模式&#xff08;Decorator Pattern&#xff09;&#xff0c;也称为包装模式&#xff08;Wrapper Pattern&#xff09;&#xff0c;是结构型设计模式之一。它通过一种对客…

游戏引擎学习第43天

仓库 https://gitee.com/mrxiao_com/2d_game 介绍运动方程 今天我们将更进一步&#xff0c;探索运动方程&#xff0c;了解真实世界中的物理&#xff0c;并调整它们&#xff0c;以创建一种让玩家感觉愉悦的控制体验。这并不是在做一个完美的物理模拟&#xff0c;而是找到最有趣…

Maven(生命周期、POM、模块化、聚合、依赖管理)详解

Maven构建项目的生命周期 在Maven出现之前&#xff0c;项目构建的生命周期就已经存在&#xff0c;软件开发人员每天都在对项目进行清理&#xff0c;编译&#xff0c;测试&#xff0c;部署等工作&#xff0c;这个过程就是项目构建的生命周期。虽然大家都在不停的做构建工作&…

第六届地博会开幕,世界酒中国菜美食文化节同期启幕推动地标发展

第六届知交会暨地博会开幕&#xff0c;辽黔欧三地馆亮点纷呈&#xff0c;世界酒中国菜助力地理标志产品发展 第六届知交会暨地博会盛大开幕&#xff0c;多地展馆亮点频出&#xff0c;美食文化节同期启幕推动地标产业发展 12月9日&#xff0c;第六届粤港澳大湾区知识产权交易博…

通过“思维链”提升ChatGPT提示词质量,更好的辅助学术论文

目录 1.写在开头 2.思维链是啥 1.写在开头 对于初步接触AIGC工具的宝子们&#xff0c;可以直接用最符合你习惯的方式去使用Kimi、ChatGPT这类AI工具。想到什么问题就问什么。对于比较简单直接的问题&#xff0c;不需要去想怎么写好提示词&#xff0c;直接在聊天窗口里表述你…

nacos bootstrap.yml 和 spring.config.import 加载配置的流程区别

相关依赖 springboot:2.7.15 nacos:2.2.3 bootstrap.yml加载方式 加载流程如下图所示 从图中可以看出,&#xff1a; 1.bootstrap.yml 的加载是在 BootstrapApplicationListener.onApplicationEvent 接收到 ApplicationEnvironmentPreparedEventEvent 事件后另起一个 Sprin…