【Java集合夜话】第1篇:拨开迷雾,探寻集合框架的精妙设计
欢迎来到Java集合框架系列的第一篇文章!🌹
本系列文章将以通俗易懂的语言,结合实际开发经验,带您深入理解Java集合框架的设计智慧。🌹
若文章中有任何不准确或需要改进的地方,欢迎大家指出,让我们一起在交流中进步!🌹
文章中的所有示例代码都经过实际验证,您可以直接在项目中参考使用。如果觉得有帮助,欢迎点赞转发!🌹

目录
-
一、基础概念
- 1. 集合框架层次结构
- List家族
- Set家族
- Queue家族
- 2. Collection与Map的区别
- Collection特性
- Map特性
- 选择建议
- 3. 集合与数组对比
- 1. 集合框架层次结构
-
二、进阶特性
- 4. 泛型在集合中的应用
- 5. 集合框架的常用接口
- 6. fail-fast与fail-safe机制
- 快速失败机制
- 安全失败机制
- 使用建议
-
三、并发处理
- 7. 同步包装器详解
- 基本概念
- 工作原理
- 使用注意事项
- 最佳实践
- 7. 同步包装器详解
阅读提示:
- 如果你是初学者,建议按顺序阅读
- 如果你是有经验的开发者,可以直接跳转到感兴趣的章节
- 每个主题都配有代码示例和实践建议
Java集合框架基础精讲
在上一篇《Java集合框架学习指南》中,我们绘制了一张完整的知识地图。今天,让我们迈出探索的第一步,深入理解Java集合框架的设计精髓。
一、基础概念
1. 集合框架层次结构
Java集合框架主要分为两大体系:
- Collection:存储元素的集合,就像一个容器,可以存放多个元素
- Map:存储键值对的映射,就像一个字典,可以通过键快速找到值
Collection 体系
Collection
├── List(有序、可重复)
│ ├── ArrayList
│ ├── LinkedList
│ └── Vector
├── Set(无序、不重复)
│ ├── HashSet
│ ├── TreeSet
│ └── LinkedHashSet
└── Queue(队列)├── PriorityQueue└── Deque
List家族
List代表有序、可重复的集合,就像我们排队一样,每个人都有明确的位置。
- ArrayList
// 创建和添加元素
List<String> fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("橙子");// 按索引访问
System.out.println(fruits.get(0)); // 输出:苹果// 插入和删除
fruits.add(1, "葡萄"); // 在索引1处插入
fruits.remove("香蕉"); // 删除指定元素
- 特点:查询快,增删慢
- 场景:适合频繁查询,较少增删的场景
- 应用:展示列表、数据缓存等
- LinkedList
// 创建和操作LinkedList
LinkedList<String> tasks = new LinkedList<>();
tasks.addFirst("任务1"); // 添加到开头
tasks.addLast("任务2"); // 添加到结尾
tasks.removeFirst(); // 移除第一个
tasks.removeLast(); // 移除最后一个
- 特点:增删快,查询慢
- 场景:适合频繁增删,较少查询的场景
- 应用:任务队列、消息队列等
Set家族
Set代表无序、不重复的集合,就像一个集市,东西只能有一份。
- HashSet
// 创建和使用HashSet
Set<String> tags = new HashSet<>();
tags.add("Java");
tags.add("Python");
tags.add("Java"); // 重复元素不会被添加
System.out.println(tags); // 输出:[Java, Python]// 判断元素是否存在
boolean hasJava = tags.contains("Java"); // 返回true
- 特点:查询快,无序
- 场景:需要去重的场景
- 应用:标签系统、去重统计等
- TreeSet
// 创建和使用TreeSet
TreeSet<Integer> scores = new TreeSet<>();
scores.add(85);
scores.add(92);
scores.add(78);
System.out.println(scores); // 自动排序:[78, 85, 92]// 范围查询
System.out.println(scores.ceiling(80)); // 大于等于80的最小值
System.out.println(scores.floor(90)); // 小于等于90的最大值
- 特点:有序(自然顺序或自定义顺序)
- 场景:需要排序的去重场景
- 应用:排行榜、成绩统计等
Queue家族
Queue代表队列,就像排队买票,先来先服务。
- PriorityQueue
// 创建优先队列
PriorityQueue<String> taskQueue = new PriorityQueue<>((a, b) -> b.length() - a.length()); // 按字符串长度降序排列
taskQueue.offer("短任务");
taskQueue.offer("非常长的任务");
taskQueue.offer("中等任务");// 获取任务
System.out.println(taskQueue.poll()); // 输出:非常长的任务
- 特点:自动排序的队列
- 场景:需要按优先级处理的场景
- 应用:任务调度、事件处理等
- ArrayDeque
// 作为栈使用
ArrayDeque<String> stack = new ArrayDeque<>();
stack.push("第一层");
stack.push("第二层");
System.out.println(stack.pop()); // 输出:第二层// 作为队列使用
ArrayDeque<String> queue = new ArrayDeque<>();
queue.offer("第一个");
queue.offer("第二个");
System.out.println(queue.poll()); // 输出:第一个
- 特点:双端队列,可以作为栈或队列使用
- 场景:需要同时支持栈和队列操作的场景
- 应用:撤销重做、历史记录等
实践建议
- 选择合适的集合类型
// 需要频繁查询
List<User> userList = new ArrayList<>();// 需要频繁增删
List<Message> messageQueue = new LinkedList<>();// 需要去重
Set<String> uniqueEmails = new HashSet<>();// 需要排序
Set<Score> scoreBoard = new TreeSet<>();
- 合理估计初始容量
// 如果知道大概需要存储100个元素
List<String> list = new ArrayList<>(100); // 避免频繁扩容
- 使用接口类型声明
// 推荐
List<String> list = new ArrayList<>();
Set<Integer> set = new HashSet<>();// 不推荐
ArrayList<String> list = new ArrayList<>();
HashSet<Integer> set = new HashSet<>();
小贴士:选择合适的集合类型可以显著提升程序性能。在实际开发中,要根据具体场景选择合适的实现类。
但是这里一直有个误区,大家都会觉得ArrayList查询快,插入慢,插入场景应使用LinkedList,其实道理上是这样,但是大部分场景如果是尾插法,其实ArrayList的性能和LinkedList是差不多的,大部分场景ArrayList甚至更甚一筹,在使用ArrayList的时候推荐从一开始就定义好集合大小,减少扩容成本。
2. Collection 与 Map 的区别与应用
Collection 特性与应用
Collection 接口是所有集合的根接口,主要用于存储单个元素的集合。
基本操作
// 创建集合
Collection<String> collection = new ArrayList<>();// 添加元素
collection.add("Java");
collection.addAll(Arrays.asList("Python", "Go"));// 删除元素
collection.remove("Java");// 判断包含
boolean hasGo = collection.contains("Go");// 获取大小
int size = collection.size();// 直接遍历(实现了Iterable接口)
for (String item : collection) {System.out.println(item);
}
常见应用场景
- 存储同类型元素集合
// 存储用户列表
Collection<User> users = new ArrayList<>();
users.add(new User("张三"));
users.add(new User("李四"));// 存储唯一标识符
Collection<String> ids = new HashSet<>();
ids.add("A001");
ids.add("A002");
- 批量数据处理
// 批量处理订单
Collection<Order> orders = getOrders();
orders.removeIf(order -> order.getStatus().equals("CANCELLED"));
orders.forEach(Order::process);
Map 特性与应用
Map 接口专门用于存储键值对映射关系,通过键可以快速找到对应的值。
基本操作
// 创建Map
Map<String, User> userMap = new HashMap<>();// 添加键值对
userMap.put("u001", new User("张三"));
userMap.put("u002", new User("李四"));// 获取值
User user = userMap.get("u001");// 检查键是否存在
boolean hasKey = userMap.containsKey("u001");
boolean hasValue = userMap.containsValue(user);// 删除键值对
userMap.remove("u001");// 获取所有键或值
Set<String> keys = userMap.keySet();
Collection<User> values = userMap.values();// 遍历键值对
for (Map.Entry<String, User> entry : userMap.entrySet()) {System.out.println(entry.getKey() + ": " + entry.getValue());
}
常见应用场景
- 缓存实现
// 简单的缓存实现
Map<String, Object> cache = new HashMap<>();
cache.put("userConfig", loadUserConfig());
cache.put("systemConfig", loadSystemConfig());// 带过期时间的缓存
Map<String, CacheEntry> timeCache = new HashMap<>();
timeCache.put("data", new CacheEntry(data, System.currentTimeMillis() + 3600000));
- 数据分组统计
// 统计单词出现频率
Map<String, Integer> wordCount = new HashMap<>();
for (String word : words) {wordCount.merge(word, 1, Integer::sum);
}// 按类别分组
Map<String, List<Product>> productByCategory = new HashMap<>();
for (Product product : products) {productByCategory.computeIfAbsent(product.getCategory(), k -> new ArrayList<>()).add(product);
}
选择建议
- 使用Collection场景:
- 需要存储同类型元素集合
- 需要频繁遍历数据
- 不需要键值对关联
- 使用Map场景:
- 需要键值对应关系
- 需要根据键快速查找值
- 需要数据分组或统计
性能考虑
// Collection性能优化
Collection<String> list = new ArrayList<>(1000); // 预设容量
Collection<String> set = new HashSet<>(1000, 0.75f); // 预设容量和负载因子// Map性能优化
Map<String, User> map = new HashMap<>(1000); // 预设容量
Map<String, User> linkedMap = new LinkedHashMap<>(1000, 0.75f, true); // 按访问顺序
小贴士:
- Collection 适合对元素进行遍历和批量操作
- Map 适合需要快速查找和建立关联关系的场景
- 在初始化时,尽可能指定合适的初始容量,避免频繁扩容
- 根据实际需求选择合适的实现类,如需要排序可以选择 TreeMap/TreeSet
3. 集合与数组对比
让我们通过一个简单的对比表格来了解数组和集合的主要区别:
| 特性 | 数组 | 集合 |
|---|---|---|
| 长度 | 固定长度 | 动态可变 |
| 数据类型 | 支持基本类型和引用类型 | 只支持引用类型 |
| 性能 | 较好(直接内存寻址) | 较差(需要额外开销) |
| 功能特性 | 只能存储和访问 | 提供丰富的操作方法 |
// 数组示例
int[] numbers = new int[5]; // 固定长度为5
String[] names = {"Tom", "Jerry"}; // 初始化固定内容// 集合示例
List<Integer> numberList = new ArrayList<>(); // 动态长度
numberList.add(1); // 自动扩容
选择建议:当数据量固定且明确时使用数组,需要动态管理数据时使用集合。
4. 泛型在集合中的应用
// 不使用泛型
List list = new ArrayList();
list.add("Hello");
String str = (String) list.get(0); // 需要强制转换// 使用泛型
List<String> list = new ArrayList<>();
list.add("Hello");
String str = list.get(0); // 无需转换
正常来说,已知类型的情况下,我们将类型给定义出来是最好的,可以为我们减少很多不必要的麻烦。
5. 集合框架的常用接口
Java集合框架提供了几个核心接口,每个接口都有其特定用途:
| 接口 | 特点 | 常用实现类 | 典型应用场景 |
|---|---|---|---|
| Collection | 集合的根接口,定义基本操作 | - | 作为通用集合类型使用 |
| List | 有序、可重复、可按索引访问 | ArrayList, LinkedList | 存储列表数据,如商品列表 |
| Set | 无序、不可重复 | HashSet, TreeSet | 存储唯一元素,如用户ID |
| Queue | 队列接口,FIFO | LinkedList, PriorityQueue | 任务队列,消息处理 |
| Map | 键值对映射 | HashMap, TreeMap | 缓存,键值对应关系 |
// 常见使用示例
List<String> list = new ArrayList<>(); // 存储有序数据
Set<Integer> set = new HashSet<>(); // 存储唯一数字
Queue<Task> queue = new LinkedList<>(); // 任务队列
Map<String, User> map = new HashMap<>(); // 用户信息映射
小贴士:选择合适的接口类型可以让代码更灵活,建议优先使用接口类型声明变量。
6. fail-fast 与 fail-safe 机制
快速失败机制
fail-fast 是Java集合的一种错误检测机制,在用迭代器遍历集合时,如果发现集合被修改,会立即抛出 ConcurrentModificationException 异常。
示例代码
// fail-fast示例
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");// 错误示范:直接修改集合
for (String item : list) {if ("A".equals(item)) {list.remove(item); // 会抛出ConcurrentModificationException}
}// 正确做法:使用迭代器修改
Iterator<String> it = list.iterator();
while (it.hasNext()) {String item = it.next();if ("A".equals(item)) {it.remove(); // 正确的删除方式}
}
多线程场景
// 多线程环境下的fail-fast
List<String> list = new ArrayList<>();
list.add("A");
list.add("B");// 一个线程遍历
new Thread(() -> {for (String item : list) {try {Thread.sleep(100);System.out.println(item);} catch (InterruptedException e) {}}
}).start();// 另一个线程修改
new Thread(() -> {try {Thread.sleep(50);list.add("C"); // 可能触发ConcurrentModificationException} catch (InterruptedException e) {}
}).start();
安全失败机制
fail-safe 机制在遍历时会在集合的副本上操作,因此在遍历过程中对原集合的修改不会反映在遍历结果中。
示例代码
// fail-safe示例
CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();
safeList.add("A");
safeList.add("B");// 可以安全遍历和修改
for (String item : safeList) {System.out.println(item);safeList.add("C"); // 不会抛出异常,但遍历的是副本
}// 并发Map的安全遍历
ConcurrentHashMap<String, String> safeMap = new ConcurrentHashMap<>();
safeMap.put("key1", "value1");
safeMap.put("key2", "value2");for (Map.Entry<String, String> entry : safeMap.entrySet()) {System.out.println(entry.getKey());safeMap.put("key3", "value3"); // 安全的并发修改
}
使用建议
- 单线程环境:
// 使用迭代器的remove方法
Iterator<String> it = list.iterator();
while (it.hasNext()) {String item = it.next();if (needToRemove(item)) {it.remove();}
}// 或者使用removeIf方法
list.removeIf(item -> needToRemove(item));
- 多线程环境:
// 使用线程安全的集合类
List<String> safeList = new CopyOnWriteArrayList<>();
Map<String, String> safeMap = new ConcurrentHashMap<>();// 或者使用同步包装器
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
synchronized (syncList) {for (String item : syncList) {// 安全地处理元素}
}
小贴士:
- 在单线程环境中,优先使用迭代器的方法进行修改
- 在多线程环境中,优先使用线程安全的集合类
- fail-safe 虽然安全,但会带来额外的内存开销
- 需要实时性的场景要谨慎使用 fail-safe 机制
7. 同步包装器详解
同步包装器(Synchronized Wrappers)是 Collections 工具类提供的一种将非线程安全的集合转换为线程安全的集合的机制。
基本概念
同步包装器通过装饰器模式,在原有集合的所有方法上添加 synchronized 关键字来实现线程安全:
// 创建同步包装器
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
Set<String> syncSet = Collections.synchronizedSet(new HashSet<>());
Map<String, String> syncMap = Collections.synchronizedMap(new HashMap<>());
工作原理
// 简化的内部实现原理
public static <T> List<T> synchronizedList(List<T> list) {return new SynchronizedList<>(list); // 返回一个同步包装类
}static class SynchronizedList<E> implements List<E> {private final List<E> list; // 持有原始列表的引用private final Object mutex; // 同步锁对象// 所有方法都使用 synchronized 关键字public void add(E e) {synchronized (mutex) {list.add(e);}}public E get(int index) {synchronized (mutex) {return list.get(index);}}
}
使用注意事项
- 迭代时需要手动同步
List<String> list = Collections.synchronizedList(new ArrayList<>());// 错误方式:可能导致并发问题
for (String item : list) {// 处理元素
}// 正确方式:手动同步
synchronized (list) {for (String item : list) {// 处理元素}
}
- 批量操作的原子性
List<String> list = Collections.synchronizedList(new ArrayList<>());// 非原子操作,需要额外同步
synchronized (list) {if (!list.contains("A")) {list.add("A");}
}
最佳实践
- 低并发场景的简单实现
// 适合并发访问少的场景
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
- 高并发场景应选择并发集合
// 更适合并发访问多的场景
List<String> concurrentList = new CopyOnWriteArrayList<>();
Map<String, String> concurrentMap = new ConcurrentHashMap<>();
- 需要原子操作时使用同步块
List<String> list = Collections.synchronizedList(new ArrayList<>());
synchronized (list) {// 需要原子性的复合操作if (list.isEmpty()) {list.add("First");}
}
核心提示:
- 同步包装器适合简单的线程安全需求
- 高并发场景建议使用专门的并发集合
- 注意迭代和复合操作时的同步处理
- 考虑性能需求选择合适的线程安全实现
总结
本文详细介绍了Java集合框架的基础知识,主要包括:
-
集合框架的整体架构
- Collection和Map两大体系
- 主要接口和实现类的特点
-
核心特性
- 泛型的应用
- fail-fast与fail-safe机制
- 同步包装器的使用
-
实践建议
- 集合类选择的考虑因素
- 性能优化的关键点
- 并发场景的最佳实践
通过本文的学习,相信你已经对Java集合框架有了一个清晰的认识。在实际开发中,合理使用这些知识点,可以帮助我们写出更优雅、更高效的代码。
下期预告
在Java集合框架这片广阔的知识海洋中,我们今天完成了第一次探索。而这仅仅是一个开始,在下一篇文章中,我们将继续深入Collection这个核心接口家族,去探索更多的技术奥秘:
🌟 我们将一起:
- 揭开Collection接口的设计智慧
- 解读核心方法的源码实现
- 探究各个实现类的内部机制
- 分享实战中的性能优化技巧
- 传授源码级别的最佳实践
技术的学习是一场永不停歇的旅程,而我很幸运能够与你同行。如果这篇文章对你有所帮助,请别忘了点赞、关注、收藏!你的每一个互动,都是我继续创作的动力!🌹🌹🌹
愿我们能在技术的道路上携手前行,共同进步!🌹🌹🌹
“种一棵树最好的时间是十年前,其次是现在。”
学习也是如此,让我们一起在技术的沃土上耕耘,收获知识的果实!
相关文章:
【Java集合夜话】第1篇:拨开迷雾,探寻集合框架的精妙设计
欢迎来到Java集合框架系列的第一篇文章!🌹 本系列文章将以通俗易懂的语言,结合实际开发经验,带您深入理解Java集合框架的设计智慧。🌹 若文章中有任何不准确或需要改进的地方,欢迎大家指出,让我…...
VSCode创建VUE项目(四)增加用户Session管理
将用户信息存储或者更新到Session sessionStorage.setItem("userID",loginform.value.username); sessionStorage.setItem(loginTime, Date.now()); 获取Session信息 const storedUserInfo sessionStorage.getItem(userID); const loginTime sessionStorage.get…...
线性代数(1)用 excel 计算鸡兔同笼
线性代数excel计算鸡兔同笼 案例:鸡兔同笼问题的三种解法(递进式教学)一、问题描述二、方程式解法(基础版)步骤解析 三、线性代数解法(进阶版)1. 方程组转化为矩阵形式2. 矩阵求解(逆…...
Qt中多线程
在Qt中实现多线程主要有两种常用方式:基于QThread的子类化和QObjectmoveToThread的Worker模式。以下是详细说明和示例代码: 1. 传统方法:继承 QThread(适用于简单任务) #include <QThread> #include <QDebug…...
Grokking System Design 系统设计面试问题
《Grokking the System Design Interview》列举了多个经典的系统设计题目,通常按照 不同的业务场景和技术难点 进行分类。以下是一些常见的分类和题目示例: 1. 社交网络类 设计 Twitter(支持关注/取关、推文、Feed 流) 设计 Facebook Messenger(即时聊天,支持在线/离线状…...
Android Launcher3 首屏图标锁定技术方案解析
一、需求背景与技术挑战 在Android 13系统定制开发中,需实现Launcher首屏图标固定功能。该需求需在以下技术维度进行突破: 拖拽事件拦截机制:需精准识别拖拽目标区域 布局层级判定:准确识别第一屏的布局标识 跨屏操作限制&…...
hubilder打包ios app, 并上传TestFlight
目录 一 前提条件 不是该项目成员解决 1. 直接找到该项目的管理人员去设置你的账号 2. 直接重新生成APPID(一般不建议的,可以查看) 3. 如果是离职人员,可以让他将项目权限转让出来 - 如何转让应用 - DCloud问答 未申请ios证书和描述文件 APP ID 的…...
AI实干家:HK深度体验-【第7篇-新加坡与香港家办业务对比】
PART I 家族办公室(家办)的定义与统计口径分析 家族办公室(Family Office, FO)的统计口径因地区、政策及数据来源差异而有所不同,需结合官方定义与第三方研究综合判断: 一、家办定义与统计口径 核心定义&…...
Java集成MQTT和Kafka实现稳定、可靠、高性能的物联网消息处理系统
Java集成MQTT和Kafka实现高可用方案 1. 概述 在物联网(IoT)和分布式系统中,消息传递的可靠性和高可用性至关重要。本文将详细介绍如何使用Java集成MQTT和Kafka来构建一个高可用的消息处理系统。 MQTT(消息队列遥测传输)是一种轻量级的发布/订阅协议,适用于资源受限的设备和…...
【总结篇】java多线程,新建线程有几种写法,以及每种写法的优劣势
java多线程 新建线程有几种写法,以及每种写法的优劣势 [1/5]java多线程 新建线程有几种写法–继承Thread类以及他的优劣势[2/5]java多线程-新建线程有几种写法–实现Runnable接口以及他的优劣势[3/5]java多线程 新建线程有几种写法–实现Callable接口结合FutureTask使用以及他的…...
剑指 Offer II 107. 矩阵中的距离
comments: true edit_url: https://github.com/doocs/leetcode/edit/main/lcof2/%E5%89%91%E6%8C%87%20Offer%20II%20107.%20%E7%9F%A9%E9%98%B5%E4%B8%AD%E7%9A%84%E8%B7%9D%E7%A6%BB/README.md 剑指 Offer II 107. 矩阵中的距离 题目描述 给定一个由 0 和 1 组成的矩阵 mat …...
雅可比行列式
定义和推导 雅可比行列式,它是以n个n元函数的偏导数为元素的行列式。以下是雅可比式的推导过程: 二阶雅可比式的推导以二重积分中的极坐标变换为例,设 : ,则 x 和 y 的全微分分别为: 可以将 dx 与 dy 视作…...
UMA架构下的GPU 显存
GPU 显存 (Graphics Memory) 在大多数现代设备(包括 Android 手机、嵌入式设备等)上,确实是使用 DDR(Double Data Rate SDRAM) 类型的内存。 不过,具体实现方式根据硬件架构有所不同,主要分为以…...
【大模型基础_毛玉仁】3.2 上下文学习
目录 3.2 上下文学习3.2.1 上下文学习的定义3.2.2 演示示例选择1)直接检索2)聚类检索3)迭代检索 3.2.3 性能影响因素 3.2 上下文学习 随模型训练数据规模和参数量的扩大,大语言模型涌现出了上下文学习(In-Context Lea…...
在 ARM 嵌入式 Linux 下使用 C/C++ 实现 MQTT
在 ARM 嵌入式 Linux 下使用 C/C 实现 MQTT 通信是一个常见的需求,尤其是在资源受限的环境中。以下是一个详细的教程,使用 Eclipse Paho C Client 库来实现 MQTT 客户端。 1. 安装 Eclipse Paho C Client 库 Eclipse Paho C Client 是一个轻量级的 MQTT…...
Oraclelinux问题-/var/log/pcp/pmlogger/目录超大
有套19c rac环境,操作系统是oracle linux 8.10,日常巡检时发现/var/log/pcp/pmlogger/目录超大,如下 [rootdb1 ~]# du -sh /var/log/pcp/pmlogger/* 468G /var/log/pcp/pmlogger/db 1.3G /var/log/pcp/pmlogger/oracle06-106 754M /…...
【大语言模型_8】vllm启动的模型通过fastapi封装增加api-key验证
背景: vllm推理框架启动模型不具备api-key验证。需借助fastapi可以实现该功能 代码实现: rom fastapi import FastAPI, Header, HTTPException, Request,Response import httpx import logging# 创建 FastAPI 应用 app FastAPI() logging.basicConfig(…...
学习笔记 ASP.NET Core Web API 8.0部署到iis
一.修改配置文件 修改Program.cs配置文件将 if (app.Environment.IsDevelopment()) {app.UseSwagger();app.UseSwaggerUI(); }修改为 app.UseSwagger(); app.UseSwaggerUI(); 二.安装ASP.NET Core Runtime 8.0.14 文件位置https://dotnet.microsoft.com/en-us/download/do…...
Python散点图(Scatter Plot):高阶分析、散点图矩阵、三维散点图及综合应用
散点图:数据分析的利器 在数据分析领域,散点图是一种直观且强大的可视化工具,广泛应用于揭示变量间的相关性以及识别数据集中的异常值。本文将深入探讨散点图的这两种关键功能,并结合实际案例与Python代码示例,带您全面了解散点图的应用。 一、散点图如何展示变量间的相…...
第5章:Docker镜像管理实战:构建、推送与版本控制
第5章:Docker镜像管理实战:构建、推送与版本控制 作者:DogDog_Shuai 阅读时间:约25分钟 难度:中级 目录 第5章:Docker镜像管理实战:构建、推送与版本控制 目录1. 引言2. Docker镜像基础 2.1 镜像结构...
Microsoft Edge浏览器的取证分析(基于Chromium)
概述 早在2019年,微软就用Chromium替换了EdgeHTML浏览器引擎,这是微软支持谷歌Chrome浏览器的一个开源项目。通过切换到Chromium,Edge与Chrome浏览器共享一个共同的架构,这意味着用于Chrome浏览器调查的取证技术也适用于Edge。 …...
汽车一键启动系统使用方便,舒适出行,轻松匹配
汽车一键启动系统 系统定义 移动管家汽车一键启动系统是装置在智能汽车上的一部分,是实现简约打火和熄火过程的一个按钮装置。它可以在原车钥匙锁头的位置改装,也能独立面板改装,现在很多高低配置的车辆都可安装。 功能特点 基本功能 启…...
C语言复习笔记--数组
今天继续来浅浅推进一下C语言的复习,这次是数组的复习,话不多说,正文开始. 数组的概念 数组是⼀组相同类型元素的集合,一种自定义类型.数组中元素个数不能为0.数组分为⼀维数组和多维数组,多维数组⼀般⽐较多⻅的是⼆维数组. 下面从一维数组说起. 一维数组的创建和…...
海康SDK协议在智联视频超融合平台中的接入方法
一. 海康SDK协议详解 海康SDK协议原理 海康SDK协议是海康威视为开发者提供的一套软件开发工具包,用于与海康设备(如摄像头、NVR、DVR等)进行通信和控制。其核心原理包括: 网络通信:基于TCP/IP协议,实现设…...
腾讯云大模型知识引擎×DeepSeek:股票分析低代码应用实践
项目背景与发展历程 在金融科技快速发展的今天,股票分析作为投资决策的核心环节,正面临数据量激增和复杂性提升的挑战。传统股票分析依赖人工处理,效率低下且成本高昂,而人工智能(AI)的引入为这一领域带来…...
深入解析 SQL Server 锁机制:如何定位并解决表锁问题
在 SQL Server 中,锁是并发控制的关键机制,确保数据的完整性和一致性。然而,在高并发环境下,锁可能导致阻塞甚至死锁,影响系统性能。因此,理解 SQL Server 的锁机制,并掌握如何定位和解决锁问题…...
Spring Boot 异步返回对象深度解析
前言 在现代高并发、高响应的应用场景中,Spring Boot 的异步处理能力是提升系统吞吐量和用户体验的关键技术之一。无论是实时数据推送、大文件传输,还是复杂异步任务调度,Spring Boot 提供了多种灵活的异步处理机制以满足不同需求。本文将从…...
【工具】C#防沉迷进程监控工具使用手册
一、软件简介 本工具用于监控指定进程的运行时长,当达到预设时间时通过声音、弹窗、窗口抖动等方式进行提醒,帮助用户合理控制程序使用时间。 软件在上篇文章。 二、系统要求 Windows 7/10/11.NET Framework 4.5 或更高版本 三、快速入门 1. 配置文件…...
【docker】--- 详解 WSL2 中的 Ubuntu 和 Docker Desktop 的区别和关系!
在编程的艺术世界里,代码和灵感需要寻找到最佳的交融点,才能打造出令人为之惊叹的作品。而在这座秋知叶i博客的殿堂里,我们将共同追寻这种完美结合,为未来的世界留下属于我们的独特印记。【WSL 】--- Windows11 迁移 WSL 超详细指南 —— 给室友换一个宿舍! 开发环境一、引…...
强大的AI网站推荐(第一集)—— Devv AI
网站:Devv AI 号称:最懂程序员的新一代 AI 搜索引擎 博主评价:我的大学所有的代码都是使用它,极大地提升了我的学习和开发效率。 推荐指数:🌟🌟🌟🌟🌟&#x…...
