JAVA 二维列表的基础操作与异常
在Java中创建二维 ArrayList
(即嵌套列表)的方法有多种,下面我将详细介绍常用的几种方式,并分析它们的区别和适用场景。
1. 使用嵌套 ArrayList
创建二维列表
方法一:直接嵌套 ArrayList
这是最常用的方法,创建一个 ArrayList
,每个元素本身又是一个 ArrayList
,从而形成二维结构。
示例代码:
import java.util.ArrayList;public class TwoDArrayListExample {public static void main(String[] args) {// 创建二维 ArrayListArrayList<ArrayList<Integer>> twoDList = new ArrayList<>();// 初始化第一行ArrayList<Integer> row1 = new ArrayList<>();row1.add(1);row1.add(2);row1.add(3);// 初始化第二行ArrayList<Integer> row2 = new ArrayList<>();row2.add(4);row2.add(5);row2.add(6);// 添加行到二维列表twoDList.add(row1);twoDList.add(row2);// 输出二维列表System.out.println(twoDList);}
}
输出:
[[1, 2, 3], [4, 5, 6]]
优点:
- 灵活,可以处理不规则的二维结构(每行的长度可以不同)。
- 易于理解和实现。
缺点:
- 需要手动管理每一行的初始化和添加,代码较繁琐。
- 访问元素的时间复杂度稍高,因为
ArrayList
是基于动态数组实现的,扩展时可能涉及数组复制。
方法二:在循环中动态初始化
这种方法通过循环来自动生成多行多列,适用于需要预定义尺寸的二维列表。
示例代码:
import java.util.ArrayList;public class DynamicTwoDArrayList {public static void main(String[] args) {int rows = 3, cols = 4;ArrayList<ArrayList<Integer>> twoDList = new ArrayList<>();// 初始化二维 ArrayListfor (int i = 0; i < rows; i++) {ArrayList<Integer> row = new ArrayList<>();for (int j = 0; j < cols; j++) {row.add(i * cols + j); // 填充数据}twoDList.add(row);}// 输出二维列表System.out.println(twoDList);}
}
输出:
[[0, 1, 2, 3], [4, 5, 6, 7], [8, 9, 10, 11]]
优点:
- 适合处理规则的矩阵结构,代码简洁。
- 便于初始化大规模数据。
缺点:
- 固定行列数量,灵活性不如直接嵌套
ArrayList
。
2. 使用 List<List<T>>
接口实现
虽然 ArrayList
是最常用的实现,但使用 List
接口定义可以增加代码的通用性和灵活性,便于将来切换到其他 List
实现(如 LinkedList
)。
示例代码:
import java.util.List;
import java.util.ArrayList;public class ListInterfaceExample {public static void main(String[] args) {List<List<String>> twoDList = new ArrayList<>();List<String> row1 = new ArrayList<>();row1.add("A");row1.add("B");List<String> row2 = new ArrayList<>();row2.add("C");row2.add("D");twoDList.add(row1);twoDList.add(row2);System.out.println(twoDList);}
}
输出:
[[A, B], [C, D]]
优点:
- 代码更加通用,便于后期维护。
- 如果将来需要换成
LinkedList
或其他List
实现,可以直接替换,代码无需大改。
缺点:
- 性能和功能上与直接使用
ArrayList
差异不大,主要优势体现在代码结构上。
3. 使用 Arrays.asList()
快速初始化
Arrays.asList()
可以用于快速初始化嵌套 ArrayList
,适用于静态、已知数据的二维列表。
示例代码:
import java.util.ArrayList;
import java.util.Arrays;public class AsListExample {public static void main(String[] args) {ArrayList<ArrayList<Integer>> twoDList = new ArrayList<>(Arrays.asList(new ArrayList<>(Arrays.asList(1, 2, 3)),new ArrayList<>(Arrays.asList(4, 5, 6)),new ArrayList<>(Arrays.asList(7, 8, 9))));System.out.println(twoDList);}
}
输出:
[[1, 2, 3], [4, 5, 6], [7, 8, 9]]
优点:
- 初始化快速,适合处理已知静态数据。
- 代码简洁明了。
缺点:
- 数据固定,不适合需要动态修改的场景。
Arrays.asList()
返回的列表大小固定,无法增加或删除元素(除非包裹在新的ArrayList
中)。
4. 使用 Collections.nCopies()
创建固定大小的二维列表
如果需要创建一个固定大小的二维 ArrayList
并填充默认值,可以使用 Collections.nCopies()
。
示例代码:
import java.util.ArrayList;
import java.util.Collections;public class NCopiesExample {public static void main(String[] args) {int rows = 3, cols = 4;ArrayList<ArrayList<Integer>> twoDList = new ArrayList<>(Collections.nCopies(rows, new ArrayList<>(Collections.nCopies(cols, 0))));System.out.println(twoDList);}
}
输出:
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
注意事项:
- 上述代码实际上会让每一行都引用同一个
ArrayList
实例,修改一行会影响所有行。因此需要深拷贝来避免这个问题。
正确版本:
import java.util.ArrayList;
import java.util.Collections;public class CorrectNCopiesExample {public static void main(String[] args) {int rows = 3, cols = 4;ArrayList<ArrayList<Integer>> twoDList = new ArrayList<>();for (int i = 0; i < rows; i++) {twoDList.add(new ArrayList<>(Collections.nCopies(cols, 0)));}System.out.println(twoDList);}
}
方法对比总结
方法 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
直接嵌套 ArrayList | 灵活、易于理解,适合不规则数据 | 初始化和管理代码较繁琐 | 小型项目或动态行列数据 |
循环动态初始化 | 适合大规模数据,代码简洁 | 行列固定,灵活性较差 | 规则矩阵结构 |
使用 List<List<T>> 接口 | 代码通用,便于维护和扩展 | 与直接嵌套 ArrayList 差异不大 | 需要考虑代码扩展性或可替换性的场景 |
Arrays.asList() 快速初始化 | 初始化快速,代码简洁 | 数据固定,无法动态增删元素 | 静态数据初始化 |
Collections.nCopies() | 快速创建固定大小的二维列表 | 需要深拷贝避免引用问题,稍复杂 | 创建统一默认值的矩阵 |
推荐使用场景
- 规则矩阵(如棋盘、表格数据):使用循环动态初始化。
- 静态、已知数据:使用
Arrays.asList()
进行快速初始化。 - 动态修改、不规则数据:直接嵌套
ArrayList
,灵活管理行列。
将二维数组转换为二维列表的方法总结
1. 使用嵌套 for-each
循环
适用场景:适用于简单的遍历和转换,适合处理基本数据类型或对象数组。
代码示例(基本数据类型):
import java.util.ArrayList;public class ForEachExample {public static void main(String[] args) {int[][] array = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};ArrayList<ArrayList<Integer>> list = new ArrayList<>();for (int[] row : array) {ArrayList<Integer> tempList = new ArrayList<>();for (int num : row) {tempList.add(num);}list.add(tempList);}System.out.println(list); // 输出: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]}
}
注意事项:
- 适用于规则或不规则的数组结构。
- 不适合处理需要索引访问的场景,因为
for-each
循环不提供索引信息。
2. 使用 Stream.forEach
流式处理
适用场景:适用于大数据处理或需要链式调用的场景,代码简洁且易于扩展。
代码示例(基本数据类型):
import java.util.ArrayList;
import java.util.Arrays;public class StreamForEachExample {public static void main(String[] args) {int[][] array = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};ArrayList<ArrayList<Integer>> list = new ArrayList<>();Arrays.stream(array).forEach(row -> {ArrayList<Integer> tempList = new ArrayList<>();Arrays.stream(row).forEach(tempList::add);list.add(tempList);});System.out.println(list); // 输出: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]}
}
注意事项:
forEach
用于流的遍历,但不能修改流本身的结构。- 适合简单转换,但对于复杂链式操作建议使用
map
和collect
。
3. 使用 Stream.map
和 collect
(推荐)
适用场景:更优雅的流式处理方式,适合复杂数据转换或链式操作。
代码示例(基本数据类型):
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class StreamMapExample {public static void main(String[] args) {int[][] array = {{1, 2, 3},{4, 5, 6},{7, 8, 9}};List<List<Integer>> list = Arrays.stream(array).map(row -> Arrays.stream(row).boxed() // 将 int 转换为 Integer.collect(Collectors.toList())).collect(Collectors.toList());System.out.println(list); // 输出: [[1, 2, 3], [4, 5, 6], [7, 8, 9]]}
}
代码示例(自定义类):
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class OXOGame {public static void main(String[] args) {OXOPlayer[][] players = {{new OXOPlayer("O")},{new OXOPlayer("X")}};List<List<OXOPlayer>> playerList = Arrays.stream(players).map(row -> Arrays.stream(row).collect(Collectors.toList())).collect(Collectors.toList());playerList.forEach(row -> {row.forEach(player -> System.out.print(player.getPlayingLetter() + " "));System.out.println();});}
}class OXOPlayer {private String playingLetter;public OXOPlayer(String letter) {this.playingLetter = letter;}public String getPlayingLetter() {return playingLetter;}
}
注意事项:
.boxed()
仅适用于基本数据类型,处理自定义类时无需使用。- 使用
map
和collect
可以实现链式操作,代码更简洁易读。
4. 使用 flatMap
展平为一维列表(进阶用法)
适用场景:当需要将二维数组转换为一维列表时使用。
代码示例(自定义类展平):
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;public class FlatMapExample {public static void main(String[] args) {OXOPlayer[][] players = {{new OXOPlayer("O"), new OXOPlayer("X")},{new OXOPlayer("X"), new OXOPlayer("O")}};List<OXOPlayer> flatList = Arrays.stream(players).flatMap(Arrays::stream).collect(Collectors.toList());flatList.forEach(player -> System.out.print(player.getPlayingLetter() + " "));// 输出: O X X O}
}class OXOPlayer {private String playingLetter;public OXOPlayer(String letter) {this.playingLetter = letter;}public String getPlayingLetter() {return playingLetter;}
}
注意事项:
flatMap
会将嵌套的流展平成单层流,适合处理需要扁平化的数据结构。- 展平后无法保留原有的二维结构,适合一维数据处理。
总结
方法 | 适用场景 | 代码简洁性 | 是否支持链式操作 | 备注 |
---|---|---|---|---|
嵌套 for-each 循环 | 简单遍历,适合初学者 | 一般 | 否 | 适用于简单数据转换,但代码较冗长 |
Stream.forEach | 简单流式处理,适合中等规模数据 | 较简洁 | 否 | 不支持复杂链式操作,适用于遍历但不适合结构修改 |
Stream.map + collect | 推荐方法,适合复杂数据转换和链式操作 | 非常简洁 | 是 | 支持高级流操作,适用于自定义类和基本数据类型 |
flatMap 展平处理 | 将二维数组转换为一维列表,适合扁平化需求 | 简洁 | 是 | 适合需要将嵌套结构扁平化处理的场景 |
在 Java 中,你提到的这个情况其实是合法的,因为它使用的是嵌套类(Nested Class),而不是定义多个顶层 public class
。
1. 嵌套类的定义
在 Java 中,可以在一个类的内部定义另一个类,这种内部类可以是 public
、protected
、private
或 default
访问级别。内部类包括:
- 静态嵌套类(Static Nested Class)
- 非静态内部类(Inner Class)
- 局部内部类(Local Class)
- 匿名内部类(Anonymous Class)
2. 你的代码属于静态嵌套类
你的代码中的 OutsideCellRangeException
是 OXOMoveException
的静态嵌套类,这是合法且常见的设计模式,特别是在定义特定异常子类时。
示例代码:
public class OXOMoveException extends RuntimeException {@Serial private static final long serialVersionUID = 1;public OXOMoveException(String message) {super(message);}// 定义枚举类型,用于表示行或列的错误public enum RowOrColumn { ROW, COLUMN }// 静态嵌套类,表示单元格超出范围的异常public static class OutsideCellRangeException extends OXOMoveException {public OutsideCellRangeException(String message) {super(message);}}
}
3. 为什么可以在 public
类中定义 public
静态嵌套类?
-
访问控制不同于顶层类:在 Java 中,一个
.java
文件中只能有一个public
的顶层类,文件名必须与该类名一致。然而,嵌套类不受此限制,可以在public
顶层类中定义多个public
嵌套类或枚举。 -
嵌套类的命名空间:嵌套类属于外部类的命名空间,
OutsideCellRangeException
被视为OXOMoveException.OutsideCellRangeException
,而不是独立的顶层类。
4. 如何使用嵌套类
你可以直接通过外部类访问嵌套的 OutsideCellRangeException
类:
public class Main {public static void main(String[] args) {try {throw new OXOMoveException.OutsideCellRangeException("Cell is outside the valid range.");} catch (OXOMoveException e) {System.out.println(e.getMessage());}}
}
输出:
Cell is outside the valid range.
静态嵌套类的特点:不依赖外部类实例:静态嵌套类不需要外部类的实例,可以直接通过外部类的名称访问。
内部类和嵌套类的区别
类型 | 是否需要外部类实例 | 可使用的访问修饰符 | 常见用途 |
---|---|---|---|
静态嵌套类 | 不需要 | public , protected , private , 默认 | 定义工具类、异常类等 |
非静态内部类 | 需要 | public , protected , private , 默认 | 访问外部类实例的成员变量 |
局部内部类 | 需要 | 无(局部作用域内有效) | 定义在方法或代码块内,临时使用的类 |
匿名内部类 | 需要 | 无 | 简化接口或抽象类的快速实现 |
-
误解:认为一个
public
类中不能有另一个public
类。- 解释:在同一个
.java
文件中,确实不能有两个public
顶层类,但嵌套类(内部类)不受此限制,可以在一个public
类中定义多个public
嵌套类。
- 解释:在同一个
总结你的前两个问题:
1. 第一个问题:异常定义的方式与 OXOGame
的兼容性
-
你的异常定义:
你将所有异常类定义为OXOMoveException
的 内部静态类(static class
)。例如:public static class InvalidBoardSizeException extends OXOMoveException {public InvalidBoardSizeException() {super("Board size is larger than 9x9 or smaller than 3x3");} }
在调用时,需要写成:
throw new OXOMoveException.InvalidBoardSizeException();
-
出现的问题:
- 未处理异常的报错: 当你在
OXOController
中抛出异常时,OXOGame
并没有显式的try-catch
来捕获这个异常,导致 IDE 提示“未处理异常”。 - 异常信息显示问题:
OXOGame
中虽然捕获了OXOMoveException
,但显示的错误信息可能是异常类的全名(如OXOMoveException$InvalidBoardSizeException
),而不是你定义的具体错误消息。
- 未处理异常的报错: 当你在
-
原因:
- 你的异常继承自
Exception
,属于 检查型异常(Checked Exception),Java 强制要求在调用的地方处理(使用try-catch
或在方法签名中throws
)。 OXOGame
中默认使用exception.toString()
输出异常,而toString()
默认返回的是类名,而不是异常消息。
- 你的异常继承自
2. 第二个问题:如何在不修改 OXOGame
的前提下解决异常处理
-
解决方法:
- 将异常从检查型异常改为非检查型异常: 将
OXOMoveException
改为继承RuntimeException
,使其成为 非检查型异常(Unchecked Exception),这样在OXOGame
中调用时不需要显式处理异常,IDE 也不会报错。public class OXOMoveException extends RuntimeException {public OXOMoveException(String message) {super(message);} }
- 重写
toString()
方法: 为了确保OXOGame
捕获异常时能正确显示自定义的错误信息,重写toString()
方法,让它返回getMessage()
:@Override public String toString() {return getMessage(); // 确保打印异常时显示的是消息而不是类名 }
- 将异常从检查型异常改为非检查型异常: 将
-
最终效果:
OXOGame
不需要任何修改,OXOController
中抛出的异常会被正确捕获并显示详细的错误信息。- 控制台输出:
Game move exception: Board size is larger than 9x9 or smaller than 3x3
异常定义对项目的影响:
-
检查型异常 vs 非检查型异常:
-
检查型异常(Checked Exception):
- 继承自
Exception
,必须显式处理。 - 如果不在调用的地方加
try-catch
或throws
,IDE 会报错。 - 影响: 会强制你修改调用该异常的方法或类,违背题目不修改
OXOGame
的要求。
- 继承自
-
非检查型异常(Unchecked Exception):
- 继承自
RuntimeException
,不需要显式处理。 - 即使调用的地方没有
try-catch
,程序仍能正常运行,异常在运行时自动处理。 - 影响: 可以在不修改
OXOGame
的情况下,正确抛出和捕获异常,符合题目要求。
- 继承自
-
-
内部类 vs 外部类异常定义:
- 内部类异常(如
OXOMoveException.InvalidBoardSizeException
):- 结构更紧凑,便于组织代码,但在引用时路径较长,可能导致代码可读性降低。
- 外部类异常(如
InvalidBoardSizeException extends OXOMoveException
):- 结构清晰,引用简便,更符合常规的异常定义习惯。
- 内部类异常(如
super
和 getMessage()
方法的解释:
-
super(message)
的作用:super(message)
是调用父类构造函数的方法。在自定义异常中,调用super(message)
将错误信息传递给Exception
或RuntimeException
的构造函数,保存到异常对象内部。- 示例:
这表示创建public InvalidBoardSizeException() {super("Board size is larger than 9x9 or smaller than 3x3"); }
InvalidBoardSizeException
对象时,错误消息"Board size is larger than 9x9 or smaller than 3x3"
会被保存到异常对象中。
-
getMessage()
的作用:getMessage()
是Throwable
类中的方法,用于返回通过super(message)
传入的错误信息。- 当你调用
exception.getMessage()
,会返回你定义的错误消息。 - 示例:
catch (OXOMoveException e) {System.out.println(e.getMessage()); // 输出:Board size is larger than 9x9 or smaller than 3x3 }
-
为什么需要重写
toString()
方法:- 默认情况下,
toString()
返回的是异常的类名和内存地址,类似:edu.uob.OXOMoveException$InvalidBoardSizeException
- 为了确保打印异常时显示自定义的错误信息,可以重写
toString()
方法,让它返回getMessage()
:@Override public String toString() {return getMessage(); }
- 这样,即使调用的是
System.out.println(exception)
,也会输出具体的错误消息,而不是类名。
- 默认情况下,
总结:
- 你的异常定义(内部静态类)是正确的,但因为它们是 检查型异常,Java 强制要求在调用时显式处理,导致在
OXOGame
中无法直接兼容。 - 将异常改为非检查型异常(继承
RuntimeException
) 可以绕开显式处理的要求,满足题目不修改OXOGame
的限制。 - 使用
super(message)
传递错误信息,使用getMessage()
获取错误信息,重写toString()
确保异常信息正确显示。
相关文章:
JAVA 二维列表的基础操作与异常
在Java中创建二维 ArrayList(即嵌套列表)的方法有多种,下面我将详细介绍常用的几种方式,并分析它们的区别和适用场景。 1. 使用嵌套 ArrayList 创建二维列表 方法一:直接嵌套 ArrayList 这是最常用的方法,…...

将仓库A分支同步到仓库B分支,并且同步commit提交
一、 问题 有一仓库A 和 一仓库B, 需要将仓库A分支a1所有提交同步推送到仓库B分支b1上 二、 解决 2.1、 首先需要仓库A、仓库B的权限, 2.2、将仓库A clone到本地, 进入A目录,并且切换到a1分支 cd A ## A 为A仓库clone到本地代…...

使用java代码操作rabbitMQ收发消息
SpringAMQP 将来我们开发业务功能的时候,肯定不会在控制台收发消息,而是应该基于编程的方式。由于RabbitMQ采用了AMQP协议,因此它具备跨语言的特性。任何语言只要遵循AMQP协议收发消息,都可以与RabbitMQ交互。并且RabbitMQ官方也…...

mysql8安装时提示-缺少Microsoft Visual C++ 2019 x64 redistributable
MySQL8.0安装包mysql-8.0.1-winx64进行安装,提示:This application requires Visual Studio 2019 x64Redistributable, Please install the Redistributable then runthis installer again。出现这个错误是因为我们电脑缺少Microsoft Visual C 这个程序&…...

WindowsServer搭建内网Gitea【中文更方便使用】
特点: 轻量级:占用系统资源少,对服务器硬件要求较低,适合小型企业或团队使用。部署和维护相对简单,即使没有专业的运维人员也能轻松搭建。 功能齐全:具备基本的代码托管功能,如仓库管理、分支管…...

leetcode 907. 子数组的最小值之和
题目如下 数据范围 观察数据范围理论上平方复杂度的算法计算次数逼近1e9还不至于超时,但是由于有mod 1e9导致超时。所以本题不能靠暴力枚举来解决。 所以我们可以思考如何在枚举上面减少计算次数:第一种枚举法:最外层i控制子数组的左边界&…...
WordPress自定义.js文件排序实现方法
在WordPress中,要将插件引用的.js文件放到所有.js文件之后加载,可以通过以下方法实现: 方法一:调整wp_enqueue_script的加载顺序 在插件的主文件中,使用wp_enqueue_script函数加载.js文件时,将$in_footer…...

摄像头模块烟火检测
工作原理 基于图像处理技术:分析视频图像中像素的颜色、纹理、形状等特征。火焰通常具有独特的颜色特征,如红色、橙色等,且边缘呈现不规则形状,还会有闪烁、跳动等动态特征;烟雾则表现为模糊、无固定形状,…...

【拼十字——树状数组】
题目 暴力代码 30% #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e5 10; const int mod 1e9 7; int n; int l[N], w[N], c[N]; int main() {cin >> n;ll ans 0;for (int i 1; i < n; i){cin >> l[i] >> …...

脚手架开发【实战教程】prompts + fs-extra
创建项目 新建文件夹 mycli_demo 在文件夹 mycli_demo 内新建文件 package.json {"name": "mycli_demo","version": "1.0.0","bin": {"mycli": "index.js"},"author": "","l…...

Fiddler Classic(HTTP流量代理+半汉化)
目录 一、关于Fiddler (一) Fiddler Classic (二) Fiddler Everywhere (三) Fiddler Everywhere Reporter (四) FiddlerCore (五) 总结 二、 软件安全性 1. 软件安装包 2. 软件汉化dll 三、安装与半汉化 1. 正常打开安装包点击下一步安装即可,安装路径自…...

基于yolov11的阿尔兹海默症严重程度检测系统python源码+onnx模型+评估指标曲线+精美GUI界面
【算法介绍】 基于YOLOv11的阿尔兹海默症严重程度检测系统是一种创新的医疗辅助工具,旨在通过先进的计算机视觉技术提高阿尔兹海默症的早期诊断和病情监测效率。阿尔兹海默症是一种渐进性的神经退行性疾病,通常表现为认知障碍、记忆丧失和语言障碍等症状…...
玩转Docker | 使用Docker部署httpd服务
玩转Docker | 使用Docker部署httpd服务 前言一、准备工作环境确认检查操作系统准备网站目录和配置文件二、拉取httpd镜像三、运行httpd容器运行容器命令检查容器状态四、验证httpd服务浏览器访问测试错误排查五、容器管理与维护查看容器状态停止和启动容器更新网站内容和配置六…...

力扣1022. 从根到叶的二进制数之和(二叉树的遍历思想解决)
Problem: 1022. 从根到叶的二进制数之和 文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的先序遍历) 1.在先序遍历的过程中,用一个变量path记录并更新其经过的路径上的值,当遇到根节点时再将其加到结果值res上; 2.该题…...

排序算法--基数排序
核心思想是按位排序(低位到高位)。适用于定长的整数或字符串,如例如:手机号、身份证号排序。按数据的每一位从低位到高位(或相反)依次排序,每次排序使用稳定的算法(如计数排序&#…...

【AIGC魔童】DeepSeek核心创新技术(二):MLA
【AIGC魔童】DeepSeek核心创新技术(二):MLA 1. MLA框架的定义与背景2. MLA框架的技术原理(1)低秩联合压缩(2)查询的低秩压缩(3)旋转位置嵌入(RoPE)…...
Mac: docker安装以后报错Command not found: docker
文章目录 前言解决办法(新的)解决步骤(原来的)不推荐总结 前言 本操作参考 http://blog.csdn.net/enhenglhm/article/details/137955756 原作者,更详细请,查看详细内容请关注原作者。 一般,…...

Golang 并发机制-7:sync.Once实战应用指南
Go的并发模型是其突出的特性之一,但强大的功能也带来了巨大的责任。sync.Once是由Go的sync包提供的同步原语。它的目的是确保一段代码只执行一次,而不管有多少协程试图执行它。这听起来可能很简单,但它改变了并发环境中管理一次性操作的规则。…...

react关于手搓antd pro面包屑的经验(写的不好请见谅)
我们先上代码,代码里面都有注释,我是单独写了一个组件,方便使用,在其他页面引入就行了 还使用了官方的Breadcrumb组件 import React, { useEffect, useState } from react; import { Breadcrumb, Button } from antd; import { …...

Android修行手册-五种比较图片相似或相同
Unity3D特效百例案例项目实战源码Android-Unity实战问题汇总游戏脚本-辅助自动化Android控件全解手册再战Android系列Scratch编程案例软考全系列Unity3D学习专栏蓝桥系列ChatGPT和AIGC👉关于作者 专注于Android/Unity和各种游戏开发技巧,以及各种资源分享(网站、工具、素材…...
生成xcframework
打包 XCFramework 的方法 XCFramework 是苹果推出的一种多平台二进制分发格式,可以包含多个架构和平台的代码。打包 XCFramework 通常用于分发库或框架。 使用 Xcode 命令行工具打包 通过 xcodebuild 命令可以打包 XCFramework。确保项目已经配置好需要支持的平台…...

Redis相关知识总结(缓存雪崩,缓存穿透,缓存击穿,Redis实现分布式锁,如何保持数据库和缓存一致)
文章目录 1.什么是Redis?2.为什么要使用redis作为mysql的缓存?3.什么是缓存雪崩、缓存穿透、缓存击穿?3.1缓存雪崩3.1.1 大量缓存同时过期3.1.2 Redis宕机 3.2 缓存击穿3.3 缓存穿透3.4 总结 4. 数据库和缓存如何保持一致性5. Redis实现分布式…...
在HarmonyOS ArkTS ArkUI-X 5.0及以上版本中,手势开发全攻略:
在 HarmonyOS 应用开发中,手势交互是连接用户与设备的核心纽带。ArkTS 框架提供了丰富的手势处理能力,既支持点击、长按、拖拽等基础单一手势的精细控制,也能通过多种绑定策略解决父子组件的手势竞争问题。本文将结合官方开发文档,…...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

使用 SymPy 进行向量和矩阵的高级操作
在科学计算和工程领域,向量和矩阵操作是解决问题的核心技能之一。Python 的 SymPy 库提供了强大的符号计算功能,能够高效地处理向量和矩阵的各种操作。本文将深入探讨如何使用 SymPy 进行向量和矩阵的创建、合并以及维度拓展等操作,并通过具体…...

【分享】推荐一些办公小工具
1、PDF 在线转换 https://smallpdf.com/cn/pdf-tools 推荐理由:大部分的转换软件需要收费,要么功能不齐全,而开会员又用不了几次浪费钱,借用别人的又不安全。 这个网站它不需要登录或下载安装。而且提供的免费功能就能满足日常…...

使用Spring AI和MCP协议构建图片搜索服务
目录 使用Spring AI和MCP协议构建图片搜索服务 引言 技术栈概览 项目架构设计 架构图 服务端开发 1. 创建Spring Boot项目 2. 实现图片搜索工具 3. 配置传输模式 Stdio模式(本地调用) SSE模式(远程调用) 4. 注册工具提…...
Python 高效图像帧提取与视频编码:实战指南
Python 高效图像帧提取与视频编码:实战指南 在音视频处理领域,图像帧提取与视频编码是基础但极具挑战性的任务。Python 结合强大的第三方库(如 OpenCV、FFmpeg、PyAV),可以高效处理视频流,实现快速帧提取、压缩编码等关键功能。本文将深入介绍如何优化这些流程,提高处理…...

Axure零基础跟我学:展开与收回
亲爱的小伙伴,如有帮助请订阅专栏!跟着老师每课一练,系统学习Axure交互设计课程! Axure产品经理精品视频课https://edu.csdn.net/course/detail/40420 课程主题:Axure菜单展开与收回 课程视频:...

MLP实战二:MLP 实现图像数字多分类
任务 实战(二):MLP 实现图像多分类 基于 mnist 数据集,建立 mlp 模型,实现 0-9 数字的十分类 task: 1、实现 mnist 数据载入,可视化图形数字; 2、完成数据预处理:图像数据维度转换与…...