《Java核心三问:字符串、equals()、hashCode()的隐藏雷区与完美避坑手册》
目录
- 一.String、StringBuffer、StringBuilder的区别?
- 1. 核心区别总结
- 2. 具体实例演示
- 示例1:不可变性 vs 可变性
- 示例2:线程安全验证
- 2. 线程安全的关键:`synchronized`
- 3. 对比`StringBuilder`的非线程安全
- 4. 可视化执行流程
- 5. 进一步验证
- 6. 总结
- 二.`==` 与 `equals()` 的区别及示例
- 1. 核心区别
- 2. 具体示例分析
- 示例1:基本数据类型(`int`)
- 示例2:字符串对象
- 示例3:自定义对象
- 示例4:重写`equals()`
- 3. 特殊场景:自动装箱陷阱
- 4. 总结
- 三、hashCode()与 equals() 的关系及重写原则
- 1. `hashCode()`与`equals()`的核心关系(前者是后者的必要不充分条件)
- 2. 为什么重写`equals()`必须重写`hashCode()`?
- 3. 如何正确重写`hashCode()`?
- 4. 总结
- 5. 额外注意事项
一.String、StringBuffer、StringBuilder的区别?
1. 核心区别总结
特性 | String | StringBuffer | StringBuilder |
---|---|---|---|
不可变性 | ✅ 不可变(每次操作生成新对象) | ❌ 可变(直接在原对象修改) | ❌ 可变(直接在原对象修改) |
线程安全 | ✅(天然不可变,线程安全) | ✅(方法用synchronized 修饰) | ❌(线程不安全,性能更高) |
性能 | 低(频繁修改时) | 中(线程安全但同步开销) | 高(无同步开销) |
适用场景 | 少量修改或作为常量使用 | 多线程环境下的字符串操作 | 单线程环境下的高频字符串操作 |
2. 具体实例演示
示例1:不可变性 vs 可变性
public class StringVsStringBuffer {public static void main(String[] args) {// String的不可变性示例String str = "Hello";System.out.println("修改前String哈希码:" + System.identityHashCode(str)); // 输出初始地址str += " World";System.out.println("修改后String哈希码:" + System.identityHashCode(str)); // 地址变化System.out.println("String结果:" + str); // Hello World// StringBuffer的可变性示例StringBuffer sb = new StringBuffer("Hello");System.out.println("\n修改前StringBuffer哈希码:" + System.identityHashCode(sb)); // 初始地址sb.append(" World");System.out.println("修改后StringBuffer哈希码:" + System.identityHashCode(sb)); // 地址不变System.out.println("StringBuffer结果:" + sb); // Hello World}
}
修改前String哈希码:1956725890
修改后String哈希码:356573597
String结果:Hello World修改前StringBuffer哈希码:1735600054
修改后StringBuffer哈希码:1735600054
StringBuffer结果:Hello World
哈希码不是内存地址,可以用来确定对象的存储位置。.
示例2:线程安全验证
public class ThreadSafetyTest {public static void main(String[] args) throws InterruptedException {// StringBuffer线程安全验证StringBuffer buffer = new StringBuffer();Runnable bufferTask = () -> {for (int i = 0; i < 1000; i++) {buffer.append("a");}};Thread t1 = new Thread(bufferTask);Thread t2 = new Thread(bufferTask);t1.start();t2.start();t1.join();t2.join();System.out.println("StringBuffer长度:" + buffer.length()); // 应为2000// StringBuilder线程不安全验证StringBuilder builder = new StringBuilder();Runnable builderTask = () -> {for (int i = 0; i < 1000; i++) {builder.append("a");}};Thread t3 = new Thread(builderTask);Thread t4 = new Thread(builderTask);t3.start();t4.start();t3.join();t4.join();System.out.println("StringBuilder长度:" + builder.length()); // 可能小于2000}}
观察控制台输出
:
◦ 哈希码变化 → 证明是否生成新对象。
◦ 线程安全结果 → StringBuffer保证数据完整,StringBuilder可能丢失数据。
◦ 耗时对比 → 直观体现性能差异。
2. 线程安全的关键:synchronized
StringBuffer
的append()
方法源码如下:
public synchronized StringBuffer append(String str) {super.append(str); // 调用父类AbstractStringBuilder的append方法return this;
}
-
synchronized
关键字:确保同一时间只有一个线程能进入该方法。 -
执行流程:
-
线程t1获取锁 → 执行
append("a")
→ 释放锁。 -
线程t2获取锁 → 执行
append("a")
→ 释放锁。
- 交替执行,无并发冲突,所有操作均被正确执行。
-
3. 对比StringBuilder
的非线程安全
StringBuilder
的append()
方法未加锁:
public StringBuilder append(String str) {super.append(str); // 直接操作,无同步return this;
}
-
问题场景:
假设value
是内部存储字符的数组,count
是当前长度。- 线程t1读取
count=5
,准备写入value[5]
。 - 线程t2同时读取
count=5
,写入value[5]
。 - 最终两个线程都认为
count=6
,但实际只写入一次 → 数据丢失。
- 线程t1读取
-
结果:最终长度可能小于2000(如示例中的1983)。
4. 可视化执行流程
操作步骤 | StringBuffer(线程安全) | StringBuilder(线程不安全) |
---|---|---|
线程t1操作 | 获取锁 → 追加字符 → 释放锁 | 直接追加字符(无锁) |
线程t2操作 | 等待锁 → 获取锁 → 追加字符 → 释放锁 | 直接追加字符(可能与t1同时操作同一位置) |
结果 | 2000次追加全部生效 | 可能因并发写入冲突导致部分操作丢失 |
5. 进一步验证
可以打印每次追加后的长度,观察是否稳定增长:
java
复制
Runnable bufferTask = () -> {for (int i = 0; i < 1000; i++) {buffer.append("a");System.out.println(Thread.currentThread().getName() + ": " + buffer.length());}
};
StringBuffer
输出:长度逐步递增,无重复值。StringBuilder
输出:可能出现多个线程打印相同长度(并发冲突)。
6. 总结
-
StringBuffer
的线程安全:通过synchronized
保证操作的原子性,避免并发冲突。 -
StringBuilder
的性能优势:牺牲线程安全换取更高性能,适用于单线程场景。 -
选择依据:
- 多线程共享资源 →
StringBuffer
。 - 单线程高频操作 →
StringBuilder
。
- 多线程共享资源 →
==和equals()的区别?加实际例子,markdown输出
二.==
与 equals()
的区别及示例
1. 核心区别
比较项 | == | equals() |
---|---|---|
比较对象 | 基本类型比较值,引用类型比较内存地址 | 引用类型比较内容(需重写方法) |
默认行为 | 直接比较内存地址 | 默认比较内存地址(同== ) |
可定制性 | 不可修改 | 可通过重写方法自定义比较逻辑 |
2. 具体示例分析
示例1:基本数据类型(int
)
int a = 5;
int b = 5;
System.out.println(a == b); // true(值相同)
示例2:字符串对象
String s1 = new String("hello");
String s2 = new String("hello");
String s3 = "hello";
String s4 = "hello";// == 比较内存地址
System.out.println(s1 == s2); // false(两个堆对象地址不同)
System.out.println(s3 == s4); // true(指向常量池同一地址)// equals() 比较内容
System.out.println(s1.equals(s2)); // true(内容相同)
System.out.println(s3.equals(s4)); // true(内容相同)
注意:String中的equals方法是被重写过的,因此String对象equals方法比较的是对象的值。
示例3:自定义对象
class Person {String name;public Person(String name) { this.name = name; }
}Person p1 = new Person("Alice");
Person p2 = new Person("Alice");
Person p3 = p1;// == 比较内存地址
System.out.println(p1 == p2); // false(不同对象地址)
System.out.println(p1 == p3); // true(指向同一对象)// equals() 默认比较地址(未重写时等同于 ==)
System.out.println(p1.equals(p2)); // false(未重写equals方法)
示例4:重写equals()
class Student {String id;public Student(String id) { this.id = id; }@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Student student = (Student) o;return Objects.equals(id, student.id); // 按id比较内容}
}Student stu1 = new Student("1001");
Student stu2 = new Student("1001");
System.out.println(stu1 == stu2); // false(地址不同)
System.out.println(stu1.equals(stu2)); // true(id相同)
3. 特殊场景:自动装箱陷阱
Integer i1 = 127;
Integer i2 = 127;
System.out.println(i1 == i2); // true(缓存范围内,地址相同)Integer i3 = 128;
Integer i4 = 128;
System.out.println(i3 == i4); // false(超出缓存范围,地址不同)System.out.println(i3.equals(i4)); // true(内容相同)
4. 总结
-
==
- 基本类型:直接比较值。
- 引用类型:比较内存地址。
-
equals()
- 默认行为:同
==
(比较地址)。 - 重写后:按业务逻辑比较内容(如
String
、Integer
等已重写)。
- 默认行为:同
-
关键原则
- 若需内容比较,必须重写
equals()
。 - 重写
equals()
时,必须同时重写hashCode()
(遵循哈希契约规则)。
- 若需内容比较,必须重写
三、hashCode()与 equals() 的关系及重写原则
1. hashCode()
与equals()
的核心关系(前者是后者的必要不充分条件)
-
哈希契约(Hash Contract):
若两个对象通过equals()
判断为相等,则它们的hashCode()
必须返回相同的值。
反之,若两个对象的hashCode()
相同,equals()
不一定返回true
(哈希冲突是允许的)。 -
默认行为:
Object
类中的equals()
默认比较内存地址(==
)。hashCode()
默认返回对象的内存地址的哈希值。
2. 为什么重写equals()
必须重写hashCode()
?
关键原因:确保对象在哈希集合中正确工作。
哈希集合(如HashMap
、HashSet
)依赖以下逻辑:
-
存储时:
- 先通过
hashCode()
计算桶的位置。 - 再通过
equals()
检查桶内是否存在相同对象。
- 先通过
-
查找时:
- 同样先根据
hashCode()
定位桶,再用equals()
精确匹配。
- 同样先根据
问题场景:
若两个对象equals()
为true
但hashCode()
不同,它们会被分配到不同的桶中,导致哈希集合无法正确去重或检索。
示例:
class Person {String name;int age;@Overridepublic boolean equals(Object o) {if (this == o) return true;if (o == null || getClass() != o.getClass()) return false;Person person = (Person) o;return age == person.age && Objects.equals(name, person.name);}// 未重写hashCode()!
}public static void main(String[] args) {Person p1 = new Person("Alice", 30);Person p2 = new Person("Alice", 30);System.out.println(p1.equals(p2)); // true(内容相同)System.out.println(p1.hashCode() == p2.hashCode()); // false(哈希码不同)Set<Person> set = new HashSet<>();set.add(p1);set.add(p2);System.out.println(set.size()); // 输出2(预期应为1,违反唯一性)
}
3. 如何正确重写hashCode()
?
- 原则:
使用与equals()
中比较的属性相同的属性组合生成哈希码。 - 推荐方法:
使用Objects.hash()
工具类,传入所有参与equals()
比较的属性。
示例:
@Override
public int hashCode() {return Objects.hash(name, age); // 基于name和age生成哈希码
}
4. 总结
操作 | 必要性 |
---|---|
重写equals() | 定义对象内容相等的逻辑。 |
重写hashCode() | 确保哈希集合正确工作,遵守哈希契约(相等对象必有相同哈希码)。 |
关键点:
- 哈希码是对象在哈希表中的“地址”,
equals()
是精确匹配的“钥匙”。 - 二者必须协同工作,才能保证哈希集合(如
HashMap
、HashSet
)的正确性和性能。
违反后果:
- 数据重复:哈希集合无法去重。
- 数据丢失:无法通过
contains()
等方法正确检索对象。 - 性能下降:哈希冲突增加,桶内链表或红黑树过长。
5. 额外注意事项
- 不可变对象:
如果对象的哈希码计算依赖可变属性,当其属性改变后,哈希码会变化,可能导致哈希集合中无法找到该对象。
解决方案:设计不可变对象,或将关键属性声明为final
。 - 性能优化:
哈希码应尽量均匀分布,减少冲突。例如,避免所有对象返回相同的哈希码。
通过遵循哈希契约,可以确保对象在哈希集合中的行为符合预期,同时提升程序的可维护性和性能。
相关文章:
《Java核心三问:字符串、equals()、hashCode()的隐藏雷区与完美避坑手册》
目录 一.String、StringBuffer、StringBuilder的区别?1. 核心区别总结2. 具体实例演示示例1:不可变性 vs 可变性示例2:线程安全验证 2. 线程安全的关键:synchronized3. 对比StringBuilder的非线程安全4. 可视化执行流程5. 进一步验…...
【Java】TCP网络编程:从可靠传输到Socket实战
活动发起人小虚竹 想对你说: 这是一个以写作博客为目的的创作活动,旨在鼓励大学生博主们挖掘自己的创作潜能,展现自己的写作才华。如果你是一位热爱写作的、想要展现自己创作才华的小伙伴,那么,快来参加吧!…...
背包问题——多重背包(C语言)
代码如下: #include<stdio.h>int knapsack(int weight[], int value[], int count[], int n, int capacity) {int* dp (int*)malloc(sizeof(int) * (capacity 1));for (int i 0; i < capacity; i){dp[i] 0;}for (int i 0; i < n; i)//核心代码{fo…...
微服务》》Kubernetes (K8S) 集群配置网络》》Calico
嘻嘻嘻 以Calico 为例子 Calico官网 官网上有安装Calico插件的步骤 步骤 要在主节点 主节点 主节点 执行 kubectl create -f https://raw.githubusercontent.com/projectcalico/calico/v3.29.2/manifests/tigera-operator.yaml kubectl get pod --all-namespaces kubec…...
寄存器(内部访问)
内存中字的储存 我们之前提到过,字由两个字节组成,当我们用16位寄存器来储存时,把字分别储存在连续的两个内存单元中,高位字节放在高地址单元中,低位字节则放在低位地址单元中。 例如上图,0、1两个单元存放…...
Vue2 watch侦听器(监听器)
watch侦听器(监听器)功能是监听数据变化,执行一些业务逻辑 或 异步操作。 核心选项 handler 监听函数,接收 (newVal, oldVal) 作为参数。deep: true 深度监听对象/数组内部变化。immediate: true 在组件创建时…...
【PCB工艺】基础:电子元器件
电子原理图(Schematic Diagram)是电路设计的基础,理解电子元器件和集成电路(IC)的作用,是画好原理图的关键。 本专栏将系统讲解 电子元器件分类、常见 IC、电路设计技巧,帮助你快速掌握电子电路…...
linux性能监控的分布式集群 prometheus + grafana 监控体系搭建
prometheusgrafana分布式集群资源监控体系搭建 前言一、安装 prometheus二、在要监控的服务器上安装监听器三、prometheus服务器配置四、grafana配置大屏五、创建Linux监控看板五、监控windows服务器注意事项 前言 Prometheus 是一个开源的 分布式监控系统 和 时间序列数据…...
Ubuntu AX200 iwlwifi-cc-46.3cfab8da.0.tgz无法下载的解决办法
文章目录 前言一、检查网卡是否被识别二、确认内核模块是否可用1.AX200 wifi 要求内核5.12.检查 iwlwifi.ko 是否存在:3.如果未找到,可能是内核模块未正确生成。尝试安装 linux-modules-extra:4.再次检查 iwlwifi.ko 是否存在:5.确…...
LinkedList与链表
ArrayList的缺陷 在上一篇博客中,小编已经较为详细得给大家介绍了ArrayList这个结构了。但是ArrayList存在一些缺陷:由于其底层是一段连续空间,当在ArrayList任意位置插入或者删除元素时,就需要将后序元素整体往前或者往后搬移&am…...
CCF 编程能力认证 C++ 四级宝典
CCF编程能力等级认证(以下简称GESP)2025年四次认证时间分别为:3月22日、6月28日、9月27日、12月20日,认证方式为线下机考,认证语言包括:C、Python和Scratch三种语言,其中Scratch认证为一到四级&…...
信创系统极速文件查找:locate 命令详解
原文链接:信创系统极速文件查找:locate 命令详解 Hello,大家好啊!今天给大家带来一篇信创终端操作系统上 locate 命令详解的文章。在 Linux 及信创终端操作系统(如 统信 UOS、麒麟 KOS)中,查找…...
数据集获取
sklearn数据集 sklearn有四部分数据。其中sklearn的数据集有两部分真实的数据,一部分嵌入到了sklearn库中,即安装好sklearn后就自带了一部分数据,这些数据的规模比较小称为small toy datasets ,还有一部分数据是需要在网上下载的,sklearn提供了下载的api接口,这些数据规…...
三格电子PLC数据采集网关-工业互联的智能枢纽
在工业自动化领域,设备间的数据互通与协议兼容是核心挑战之一。三格电子推出的PLC据采集网关SG-PLC-Private,凭借其多协议兼容、高稳定性和灵活配置能力,成为工业物联网(IIoT)中实现设备互联的关键设备。本文将从产品功…...
【sgFloatDialog】自定义组件:浮动弹窗,支持修改尺寸、拖拽位置、最大化、还原、最小化、复位
sgFloatDialog <template><div :class"$options.name" v-if"visible" :size"size" :style"style"><!-- 托盘头部 --><div class"header" ref"header" dblclick.stop.prevent"dblclic…...
conda 常用命令
常用 Conda 命令整理环境管理 conda create --name 环境名 :创建新环境 conda activate 环境名 :激活环境 conda deactivate:退出环境 conda env list:列出所有环境 conda remove --name 环境名 --all :删除环…...
神聖的綫性代數速成例題10. N維矢量綫性運算、矢量由矢量組綫性表示、N個N維矢量相關性質
N 維矢量綫性運算: 設,是維矢量,是數。加法:。數乘:。 矢量由矢量組綫性表示: 設是n維矢量,若存在一組數,使得,則稱矢量可由矢量組綫性表示。 N 個 N 維矢量相關性質&…...
力扣977. 有序数组的平方(双指针技巧)
Problem: 977. 有序数组的平方 文章目录 题目描述思路Code 题目描述 思路 由于数组是非递减且包含正、负数,则假如我们将数组中的每一个元素取平方并且将其从原始的某一个位置分开成两个数组来看待(一个数组从前往后看,一个数组从后往前看&am…...
单片机flash存储也做磨损均衡
最近在做一个项目,需要保存设置数据,掉电不丢失。那么首先想到的是加个24c02,是一个eeprom,但是客户板太小,没有办法进行扩展。后面就找了一个带ee的OTP单片机,发现擦写次数有限,只有1000次&…...
第7章 类与面向对象
6-1 二维平面上的点操作(Python3) 题目描述 设计一个表示二维平面上点的类 Point。该类应该包含以下功能: 两个私有属性 _x 和 _y,分别表示点的横坐标和纵坐标。 一个构造函数 __init__,用于初始化点的坐标。 一个…...
【算法】力扣 713题:乘积小于 K 的子数组之深入思考
文章目录 前言题目:乘积小于 K 的子数组参考思路方法一:滑动窗口方法二:二分查找 参考题解方法一:滑动窗口解法方法二:二分查找解法 深入思考浮点精度?right - left 1?二分法?哈希优…...
Milvus vs. ElasticSearch:向量库检索性能测试
目录 1. 构建检索库2. 测试条件3. 测试结果4. 性能分析5. 结论 1. 构建检索库 构建通用场景库总计约2万张。构建车辆数据库总计约12万张。构建公共数据库,包括Flickr30k、COCO、nlvr2、vqa等数据集约43万张。 2. 测试条件 环境说明:分别单机部署Milvu…...
高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构
高级数据结构应用:并查集、跳表、布隆过滤器与缓存结构 在解决复杂问题时,选择合适的数据结构往往是成功的关键。本文将深入探讨四种强大而实用的高级数据结构:并查集、跳表、布隆过滤器和高效缓存结构(LRU和LFU),包括它们的原理、实现、复杂度分析和实际应用场景。 1.…...
CVPR2025 | 蚂蚁浙大提出MP-GUI算法:全方位增强MLLM的GUI理解能力
近日,计算机视觉和模式识别领域国际顶会CVPR 2025公布了论文录用结果,蚂蚁集团与浙江大学EAGLE实验室合作的论文 “MP-GUI: Modality Perception with MLLMs for GUI Understanding” 被成功录用。 IEEE国际计算机视觉与模式识别会议(CVPR&a…...
过河卒cpp动态规划
题目如下 思路 利用二维数组存储棋盘的各个点的位置,首先初始化所有位置为0,然后记马的位置为1,将m,n同时加2,避免马的位置溢出,然后对二维数组进行递推算出dp[n][m] 代码及解析如下 谢谢观看!…...
春天咋会像冬天一样
2025年3月20日,阴,天寒 遇见的事:21~24号去曲靖招生,打电话给我说换一下,换了后又没有车了,这么坑。 感受到的情绪:你知道么,换的前提是有车。开车不给报销,…...
DooTask在Linux的离线部署教程
DooTask在Linux的离线部署教程 下载安装包 从网盘中将安装包下载到本地,下载地址 通过网盘分享的文件:DooTask项目管理工具 链接: https://pan.baidu.com/s/1hGmLXonT4c8hLiDP1QBr8w?pwdgdp6 提取码: gdp6 通过网盘分享的文件:DooTask项目…...
分享下web3j 常见用法
转账 fun sendEthTransaction(privateKey: String,toAddress: String,amount: BigDecimal) {//chainIdval chainId:Long 1//url 可以从https://chainlist.org/里面获取可用节点//eth转账,bnb同理,但需发送到bnb对应节点val url "https://xxx"…...
跨域问题确认及处理
背景如下: 近期在做的项目中,有个奇怪的需求,需要在JSP项目中嵌套一个VUE项目,原因是:JSP项目是在运且不大方便重构的一个项目,新需求又想为了未来着想做一套单独的项目,无奈只能嵌套。 当项目开…...
PyCharm如何添加已有的conda环境
1、点击文件中的设置 2、在右侧选中项目下的Python解释器 3、在右侧解释器一栏找到添加解释器选项 4、选择本地解释器 5、填写信息 环境:选择现有 类型:conda conda路径:...\Anaconda\Scripts\conda.exe 环境(python路径&…...
揭开最大子段和问题的神秘面纱:从暴力法到极致优化的算法之旅
最大子段和问题:从暴力法到优化的算法解析 题目链接 题目描述 给出一个长度为 nn 的序列 aa,选出其中连续且非空的一段使得这段和最大。 输入格式 第一行是一个整数,表示序列的长度 n。第二行有 n 个整数,第 i 个整数表示序列的…...
MySQL原理:逻辑架构
目的:了解 SQL执行流程 以及 MySQL 内部架构,每个零件具体负责做什么 理解整体架构分别有什么模块每个模块具体做什么 目录 1 服务器处理客户端请求 1.1 MySQL 服务器端逻辑架构说明 2 Connectors 3 第一层:连接层 3.1 数据库连接池(Conn…...
提升模型性能:数据增强与调优实战
一、为什么需要数据增强? 数据增强通过对训练图像进行随机变换,能够有效: 增加数据多样性,防止过拟合提升模型对不同视角、光照条件的鲁棒性在数据量不足时显著提升模型性能 二、MNIST手写数字识别实战 1. 加载数据…...
Emacs 折腾日记(十八)——改变Emacs的样貌
截止到上一篇文章为止,之前教程 的内容都看完了,虽然它的后记部分提供了一些后续进阶的内容需要我们自己读手册。但是我不太想继续在elisp上死磕了。看着自己学了那么久的elisp,但是自己的emacs仍然没有半点改变,这个时候各位读者…...
VNA操作使用学习-14 再测晶振特性
再测一下4Mhz晶振,看看特性曲线,熟悉一下vna使用。 s11模式,找遍了各种format都无法显示,只有这一种(s11,Resistance)稍微显示出一个谐振,但是只有一个点。 s21模式 这是201p&#…...
CentOS7 离线下载安装 GitLab CE
依赖下载 https://vault.centos.org/7.9.2009/os/x86_64/Packages/policycoreutils-python-2.5-34.el7.x86_64.rpm 依赖安装 rpm -ivh policycoreutils-python-2.5-34.el7.x86_64.rpm 查看是否安装依赖 rpm -qa | grep policycoreutils-pythongitlab下载 https://packag…...
LeetCode 热题 100_跳跃游戏 II(79_45_中等_C++)(贪心算法)
LeetCode 热题 100_跳跃游戏 II(79_45) 题目描述:输入输出样例:题解:解题思路:思路一(贪心选择): 代码实现代码实现(思路一(贪心算法)…...
《Linux系统编程篇》Linux Socket 网络编程01 API介绍(Linux 进程间通信(IPC))——基础篇
文章目录 引言1. **创建Socket**2. **绑定Socket**3. **监听Socket**4. **接受客户端连接**5. **连接服务器**6. **发送数据**7. **接收数据**8. **发送数据(UDP)**9. **接收数据(UDP)**10. **关闭Socket**11. **设置/获取Socket选…...
系统思考—啤酒游戏经营决策沙盘模拟
再次感谢文华学院的邀请,为经纬集团管理层带来 《啤酒游戏经营决策沙盘》! 很多朋友问:“最近是不是啤酒游戏上的少了?” 其实,真正的关键不是游戏本身,而是——如何让大家真正看见复杂系统中的隐性结构。 …...
利用设计模式构建事件处理系统
在现代软件开发中,设计模式提供了一种可重用的解决方案来解决常见的设计问题。在这篇博客中,我们将探讨如何利用模板方法模式、责任链模式、建造者模式以及线程安全设计来构建一个灵活且可扩展的事件处理系统。 设计模式及其应用 1. 模板方法模式 应用…...
ThreadLocal 的详细使用指南
一、ThreadLocal 核心原理 ThreadLocal 是 Java 提供的线程绑定机制,为每个线程维护变量的独立副本。其内部通过 ThreadLocalMap 实现,每个线程的 Thread 对象都有一个独立的 ThreadLocalMap,存储以 ThreadLocal 对象为键、线程局部变量为值…...
全员DeepSeek时代,前端能做些什么?
全员DeepSeek时代,前端能做些什么? 前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,可以分享一下给大家。点击跳转到网站。 https://www.captainbed.cn/ccc #mermaid-svg-VNyL95jkz9jEXgUq {font-family:&…...
阿里云 AI 搜索产品荣获 Elastic Innovation Award 2024
阿里云AI搜索产品荣获Elastic Innovation Award 2024,该奖项于近日在新加坡ElasticON 2025的Elastic合作伙伴峰会上颁发,旨在表彰基于Elastic平台开发企业级生成式人工智能(GenAI)应用的顶尖合作伙伴,这些应用有效帮助…...
html5制作2048游戏开发心得与技术分享
2048游戏开发心得与技术分享 这里写目录标题 2048游戏开发心得与技术分享项目概述技术架构1. 核心技术栈2. 项目结构 核心功能实现1. 数据结构设计2. 移动逻辑实现3. 触摸支持 性能优化1. DOM操作优化2. 事件处理优化 开发心得1. 代码组织2. 调试技巧3. 用户体验优化 项目亮点技…...
AI日报 - 2025年3月21日
🌟 今日概览(60秒速览) ▎🤖 AGI突破 | OpenAI成立安全委员会,加速AGI治理框架构建 ▎💼 商业动向 | 微软发布医疗大模型DAX Copilot 3.0,覆盖全球临床场景 ▎📜 政策追踪 | 中国发布…...
MyBatis-Plus:告别手写 SQL 的高效之道
目录 1. MyBatis-plus 简介 2. MyBatis-Plus 快速上手 2.1 项目准备 2.2 导入 MyBatis-Plus 依赖 2.3 配置数据库连接 2.4 配置 MyBatis-Plus 日志打印 3. 使用 MyBatis-Plus 3.1 创建 model 类 3.2 创建 mapper 接口 3.3 MyBatis-Plus 映射机制 3.3.1 TableName &a…...
【AI News | 20250320】每日AI进展
AI Repos 1、servers 该仓库提供详细入门指南,用户可通过简单步骤连接Claude客户端,快速使用所有服务器功能。此项目由Anthropic管理,展示MCP的多样性与扩展性,助力开发者为大语言模型提供安全、可控的工具与数据访问。 2、awe…...
让“树和二叉树”埋在记忆土壤中--性质和概念
Nice to meet your! 目录 树的介绍: 树的创建: 二叉树的概念和结构: 二叉树的存储结构: 树的介绍: 概念和结构: 不知你们是否在现实中看见过分为两个叉的枯树,大概长这样: 那…...
210、【图论】课程表(Python)
题目 思路 这道题本质上是一个拓扑排序。每次先统计每个点的入度个数、然后再统计点与点之间的邻接关系,找到入度为0的点作为起始遍历点。之后每遍历到这个点之后,就把这个点后续的邻接关系边的点入度减去一。当某个点入度为0时,继续被加入其…...
【Linux篇】进程控制
📌 个人主页: 孙同学_ 🔧 文章专栏:Liunx 💡 关注我,分享经验,助你少走弯路! 1. 进程创建 1.1 fork函数 在linux中fork函数是非常重要的函数,它从已存在进程中创建一个…...