【Java集合夜话】第1篇:拨开迷雾,探寻集合框架的精妙设计

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

起篇

目录

  • 一、基础概念

    • 1. 集合框架层次结构
      • List家族
      • Set家族
      • Queue家族
    • 2. Collection与Map的区别
      • Collection特性
      • Map特性
      • 选择建议
    • 3. 集合与数组对比
  • 二、进阶特性

    • 4. 泛型在集合中的应用
    • 5. 集合框架的常用接口
    • 6. fail-fast与fail-safe机制
      • 快速失败机制
      • 安全失败机制
      • 使用建议
  • 三、并发处理

    • 7. 同步包装器详解
      • 基本概念
      • 工作原理
      • 使用注意事项
      • 最佳实践

阅读提示:

  • 如果你是初学者,建议按顺序阅读
  • 如果你是有经验的开发者,可以直接跳转到感兴趣的章节
  • 每个主题都配有代码示例和实践建议

Java集合框架基础精讲

在上一篇《Java集合框架学习指南》中,我们绘制了一张完整的知识地图。今天,让我们迈出探索的第一步,深入理解Java集合框架的设计精髓。

一、基础概念

1. 集合框架层次结构

Java集合框架主要分为两大体系:

  • Collection:存储元素的集合,就像一个容器,可以存放多个元素
  • Map:存储键值对的映射,就像一个字典,可以通过键快速找到值

Collection 体系

Collection
├── List(有序、可重复)
│   ├── ArrayList
│   ├── LinkedList
│   └── Vector
├── Set(无序、不重复)
│   ├── HashSet
│   ├── TreeSet
│   └── LinkedHashSet
└── Queue(队列)├── PriorityQueue└── Deque
List家族

List代表有序、可重复的集合,就像我们排队一样,每个人都有明确的位置。

  1. ArrayList
// 创建和添加元素
List<String> fruits = new ArrayList<>();
fruits.add("苹果");
fruits.add("香蕉");
fruits.add("橙子");// 按索引访问
System.out.println(fruits.get(0));  // 输出:苹果// 插入和删除
fruits.add(1, "葡萄");     // 在索引1处插入
fruits.remove("香蕉");     // 删除指定元素
  • 特点:查询快,增删慢
  • 场景:适合频繁查询,较少增删的场景
  • 应用:展示列表、数据缓存等
  1. LinkedList
// 创建和操作LinkedList
LinkedList<String> tasks = new LinkedList<>();
tasks.addFirst("任务1");   // 添加到开头
tasks.addLast("任务2");    // 添加到结尾
tasks.removeFirst();       // 移除第一个
tasks.removeLast();       // 移除最后一个
  • 特点:增删快,查询慢
  • 场景:适合频繁增删,较少查询的场景
  • 应用:任务队列、消息队列等
Set家族

Set代表无序、不重复的集合,就像一个集市,东西只能有一份。

  1. 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
  • 特点:查询快,无序
  • 场景:需要去重的场景
  • 应用:标签系统、去重统计等
  1. 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代表队列,就像排队买票,先来先服务。

  1. PriorityQueue
// 创建优先队列
PriorityQueue<String> taskQueue = new PriorityQueue<>((a, b) -> b.length() - a.length());  // 按字符串长度降序排列
taskQueue.offer("短任务");
taskQueue.offer("非常长的任务");
taskQueue.offer("中等任务");// 获取任务
System.out.println(taskQueue.poll());  // 输出:非常长的任务
  • 特点:自动排序的队列
  • 场景:需要按优先级处理的场景
  • 应用:任务调度、事件处理等
  1. 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());  // 输出:第一个
  • 特点:双端队列,可以作为栈或队列使用
  • 场景:需要同时支持栈和队列操作的场景
  • 应用:撤销重做、历史记录等

实践建议

  1. 选择合适的集合类型
// 需要频繁查询
List<User> userList = new ArrayList<>();// 需要频繁增删
List<Message> messageQueue = new LinkedList<>();// 需要去重
Set<String> uniqueEmails = new HashSet<>();// 需要排序
Set<Score> scoreBoard = new TreeSet<>();
  1. 合理估计初始容量
// 如果知道大概需要存储100个元素
List<String> list = new ArrayList<>(100);  // 避免频繁扩容
  1. 使用接口类型声明
// 推荐
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);
}
常见应用场景
  1. 存储同类型元素集合
// 存储用户列表
Collection<User> users = new ArrayList<>();
users.add(new User("张三"));
users.add(new User("李四"));// 存储唯一标识符
Collection<String> ids = new HashSet<>();
ids.add("A001");
ids.add("A002");
  1. 批量数据处理
// 批量处理订单
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());
}
常见应用场景
  1. 缓存实现
// 简单的缓存实现
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));
  1. 数据分组统计
// 统计单词出现频率
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);
}

选择建议

  1. 使用Collection场景:
  • 需要存储同类型元素集合
  • 需要频繁遍历数据
  • 不需要键值对关联
  1. 使用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); // 按访问顺序

小贴士:

  1. Collection 适合对元素进行遍历和批量操作
  2. Map 适合需要快速查找和建立关联关系的场景
  3. 在初始化时,尽可能指定合适的初始容量,避免频繁扩容
  4. 根据实际需求选择合适的实现类,如需要排序可以选择 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队列接口,FIFOLinkedList, 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");  // 安全的并发修改
}

使用建议

  1. 单线程环境:
// 使用迭代器的remove方法
Iterator<String> it = list.iterator();
while (it.hasNext()) {String item = it.next();if (needToRemove(item)) {it.remove();}
}// 或者使用removeIf方法
list.removeIf(item -> needToRemove(item));
  1. 多线程环境:
// 使用线程安全的集合类
List<String> safeList = new CopyOnWriteArrayList<>();
Map<String, String> safeMap = new ConcurrentHashMap<>();// 或者使用同步包装器
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
synchronized (syncList) {for (String item : syncList) {// 安全地处理元素}
}

小贴士:

  1. 在单线程环境中,优先使用迭代器的方法进行修改
  2. 在多线程环境中,优先使用线程安全的集合类
  3. fail-safe 虽然安全,但会带来额外的内存开销
  4. 需要实时性的场景要谨慎使用 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);}}
}

使用注意事项

  1. 迭代时需要手动同步
List<String> list = Collections.synchronizedList(new ArrayList<>());// 错误方式:可能导致并发问题
for (String item : list) {// 处理元素
}// 正确方式:手动同步
synchronized (list) {for (String item : list) {// 处理元素}
}
  1. 批量操作的原子性
List<String> list = Collections.synchronizedList(new ArrayList<>());// 非原子操作,需要额外同步
synchronized (list) {if (!list.contains("A")) {list.add("A");}
}

最佳实践

  1. 低并发场景的简单实现
// 适合并发访问少的场景
List<String> syncList = Collections.synchronizedList(new ArrayList<>());
  1. 高并发场景应选择并发集合
// 更适合并发访问多的场景
List<String> concurrentList = new CopyOnWriteArrayList<>();
Map<String, String> concurrentMap = new ConcurrentHashMap<>();
  1. 需要原子操作时使用同步块
List<String> list = Collections.synchronizedList(new ArrayList<>());
synchronized (list) {// 需要原子性的复合操作if (list.isEmpty()) {list.add("First");}
}

核心提示:

  1. 同步包装器适合简单的线程安全需求
  2. 高并发场景建议使用专门的并发集合
  3. 注意迭代和复合操作时的同步处理
  4. 考虑性能需求选择合适的线程安全实现

总结

本文详细介绍了Java集合框架的基础知识,主要包括:

  1. 集合框架的整体架构

    • Collection和Map两大体系
    • 主要接口和实现类的特点
  2. 核心特性

    • 泛型的应用
    • fail-fast与fail-safe机制
    • 同步包装器的使用
  3. 实践建议

    • 集合类选择的考虑因素
    • 性能优化的关键点
    • 并发场景的最佳实践

通过本文的学习,相信你已经对Java集合框架有了一个清晰的认识。在实际开发中,合理使用这些知识点,可以帮助我们写出更优雅、更高效的代码。

下期预告

在Java集合框架这片广阔的知识海洋中,我们今天完成了第一次探索。而这仅仅是一个开始,在下一篇文章中,我们将继续深入Collection这个核心接口家族,去探索更多的技术奥秘:

🌟 我们将一起:

  • 揭开Collection接口的设计智慧
  • 解读核心方法的源码实现
  • 探究各个实现类的内部机制
  • 分享实战中的性能优化技巧
  • 传授源码级别的最佳实践

技术的学习是一场永不停歇的旅程,而我很幸运能够与你同行。如果这篇文章对你有所帮助,请别忘了点赞、关注、收藏!你的每一个互动,都是我继续创作的动力!🌹🌹🌹

愿我们能在技术的道路上携手前行,共同进步!🌹🌹🌹

“种一棵树最好的时间是十年前,其次是现在。”
学习也是如此,让我们一起在技术的沃土上耕耘,收获知识的果实!

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

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

相关文章

网络安全知识:网络安全网格架构

在数字化转型的主导下&#xff0c;大多数组织利用多云或混合环境&#xff0c;包括本地基础设施、云服务和应用程序以及第三方实体&#xff0c;以及在网络中运行的用户和设备身份。在这种情况下&#xff0c;保护组织资产免受威胁涉及实现一个统一的框架&#xff0c;该框架根据组…

企业级云MES全套源码,支持app、小程序、H5、台后管理端

企业级云MES全套源码&#xff0c;支持app、小程序、H5、台后管理端&#xff0c;全套源码 开发环境 技术架构&#xff1a;springboot vue-element-plus-admin 开发语言&#xff1a;Java 开发工具&#xff1a;idea 前端框架&#xff1a;vue.js 后端框架&#xff…

Web爬虫利器FireCrawl:全方位助力AI训练与高效数据抓取

Web爬虫利器FireCrawl&#xff1a;全方位助力AI训练与高效数据抓取 一、FireCrawl 项目简介二、主要功能三、FireCrawl应用场景1. 大语言模型训练2. 检索增强生成&#xff08;RAG&#xff09;&#xff1a;3. 数据驱动的开发项目4. SEO 与内容优化5. 在线服务与工具集成 四、安装…

[HelloCTF]PHPinclude-labs超详细WP-Level 6Level 7Level 8Level 9-php://协议

由于Level 6-9 关的原理都是通用的, 这里就拿第6关举例, 其他的关卡同理 源码分析 定位到代码 isset($_GET[wrappers]) ? include("php://".$_GET[wrappers]) : ; 与前几关发生变化的就是 php:// 解题分析 这一关要求我们使用 php协议 php:// 协议 php://filte…

《Linux 网络架构:基于 TCP 协议的多人聊天系统搭建详解》

一、系统概述 本系统是一个基于 TCP 协议的多人聊天系统&#xff0c;由一个服务器和多个客户端组成。客户端可以连接到服务器&#xff0c;向服务器发送消息&#xff0c;服务器接收到消息后将其转发给其他客户端&#xff0c;实现多人之间的实时聊天。系统使用 C 语言编写&#x…

Maven生命周期

三套生命周期&#xff0c;项目清理&#xff0c;项目构建&#xff0c;项目生成 我们主要关注五个阶段 clean&#xff1a;移除上一次构建生成的文件compile&#xff1a;编译项目源代码test&#xff1a;使用合适的单元测试框架运行测试package&#xff1a;将编译后的文件打包&am…

【JVM】内存区域划分,类加载机制和垃圾回收机制

本篇内容为了解 JVM 的内存区域划分&#xff0c;类加载机制&#xff0c;垃圾回收机制。实际开发中几乎用不到&#xff0c;但为了某些情况我们又不得不了解。 目录 一、JVM中的内存区域划分 1.1 内存区域划分考点 二、JVM的类加载机制 2.1 类加载流程 2.2 类加载什么时候会…

v-自定义权限指令与v-if互相影响导致报错Cannot read properties of null (reading ‘insertBefore‘)

项目场景&#xff1a; vue3vite项目中报错Cannot read properties of null (reading ‘insertBefore‘) 原因分析&#xff1a; :v-自定义权限指令与v-if互相影响 <el-button text bg type"primary" click"handleWrite(detailData,项目填报)" v-hasPe…

qt下载和安装教程国内源下载地址

qt不断在更新中&#xff0c;目前qt6日渐成熟&#xff0c;先前我们到官方下载或者国内镜像直接可以下载到exe文件安装&#xff0c;但是最近几年qt官方似乎在逐渐关闭旧版本下载通道&#xff0c;列为不推荐下载。但是qt5以其广泛使用和稳定性&#xff0c;以及积累大量代码使得qt5…

k8s1.30 部署calio网络

一、介绍 网路组件有很多种&#xff0c;只需要部署其中一个&#xff0c;推荐calio。 calio是一个纯三成的数据中心网络方案&#xff0c;calico支持广泛的平台。如k8s&#xff0c;openstack等。 calio在每一个计算节点利用linux内核&#xff0c;实现了一个高效的虚拟路由器来…

navicat导出文件密码解密

文章目录 一、概念二、导出文件1、创建的数据库连接信息2、导出带密码的连接信息3、查看导出后的文件 三、Python代码解析四、参考地址 一、概念 Navicat中导出的带密码的文件后缀是.ncx结尾的&#xff0c;里面是xml格式的文件&#xff0c;存储了数据库的连接&#xff0c;方便…

实验5:Vuex状态管理

Web前端开发技术课程实验报告 实验5&#xff1a;Vuex状态管理 一、实验目的&#xff1a; 掌握Vuex的工作原理和5个核心概念。掌握Vuex API接口的使用方法。 二、实验要求&#xff1a; 掌握mutations、actions、getters的定义和使用方法&#xff0c;完成以下实验内容。上交实…

深入解析 Linux 声卡驱动:从架构到实战

在嵌入式 Linux 设备中&#xff0c;音频功能的实现离不开 Linux 声卡驱动。而 ALSA (Advanced Linux Sound Architecture) 作为 Linux 内核的音频框架&#xff0c;提供了一整套 API 和驱动模型&#xff0c;帮助开发者快速集成音频功能。本篇文章以 WM8960 音频编解码器&#xf…

windows+ragflow+deepseek实战之一excel表查询

ragflows平台部署参考文章 Win10系统Docker+DeepSeek+ragflow搭建本地知识库 ragflow通过python实现参考这篇文章 ragflow通过python实现 文章目录 背景效果1、准备数据2、创建知识库3、上传数据并解析4、新建聊天助理5、测试会话背景 前面已经基于Win10系统Docker+DeepSeek+…

【VUE】ant design vue实现表格table上下拖拽排序

适合版本&#xff1a;ant design vue 1.7.8 实现效果&#xff1a; 代码&#xff1a; <template><div class"table-container"><a-table:columns"columns":dataSource"tableData":rowKey"record > record.id":row…

vue3+Ts+elementPlus二次封装Table分页表格,表格内展示图片、switch开关、支持

目录 一.项目文件结构 二.实现代码 1.子组件&#xff08;表格组件&#xff09; 2.父组件&#xff08;使用表格&#xff09; 一.项目文件结构 1.表格组件&#xff08;子组件&#xff09;位置 2.使用表格组件的页面文件&#xff08;父组件&#xff09;位置 3.演示图片位置 ele…

ModBus TCP/RTU互转(主)(从)|| Modbus主动轮询下发的工业应用 || 基于智能网关的串口服务器进行Modbus数据收发的工业应用

目录 前言 一、ModBus TCP/RTU互转&#xff08;从&#xff09;及应用|| 1.1 举栗子 二、ModBus TCP/RTU互转&#xff08;主&#xff09; 2.1 举栗子 三、ModBus 主动轮询 3.1 Modbus主动轮询原理 3.2 Modbus格式上传与下发 3.2.1.设置Modbus主动轮询指令 3.2.2 设…

Elasticsearch 在航空行业:数据管理的游戏规则改变者

作者&#xff1a;来自 Elastic Adam La Roche 数字化客户体验不再是奢侈品&#xff0c;而是欧洲航空公司必不可少的需求。它推动了客户满意度&#xff0c;提升了运营效率&#xff0c;并创造了可持续的竞争优势。随着行业的不断发展&#xff0c;优先投资前沿数字技术和平台的航空…

CXL协议之FM(Fabric Management)解释

CXL协议中的FM功能详解 1. FM的核心作用 FM是CXL&#xff08;Compute Express Link&#xff09;架构中的核心管理实体&#xff0c;负责协调和管理CXL设备之间的通信、资源分配及拓扑结构。其核心功能包括&#xff1a; 设备发现与枚举&#xff1a;识别CXL拓扑中的设备&#x…

html5基于Canvas的经典打砖块游戏开发实践

基于Canvas的经典打砖块游戏开发实践 这里写目录标题 基于Canvas的经典打砖块游戏开发实践项目介绍技术栈核心功能实现1. 游戏初始化2. 游戏对象设计3. 碰撞检测系统4. 动画系统5. 用户界面设计 性能优化1. 渲染优化2. 内存管理 项目亮点技术难点突破项目总结 项目介绍 在这个…