Java 进阶--集合:告别数组的“僵硬”,拥抱灵活的数据容器
作者:IvanCodes
发布时间:2025年5月1日🫡
专栏:Java教程
大家好!👋 还记得我们上次聊的数组 (Array) 吗?它很基础,性能也不错,但有个致命的缺点:长度一旦定了就不能改 <🔒>!想象一下,你用数组存购物车里的商品 🛒,刚开始定了装 10 件,结果顾客想买第 11 件… 咋办?重新创建一个更大的数组,再把旧的东西搬过去?太麻烦了!😫
为了解决数组这种“僵硬”的问题,以及提供更丰富的数据组织方式,Java 提供了一套强大的 集合框架 (Java Collections Framework, JCF)。你可以把它想象成一个超级工具箱 🧰,里面有各种大小可变、功能各异的容器 🧺,专门用来高效地存储和管理对象。今天,我们就来打开这个工具箱,看看里面有哪些宝贝!✨
一、为什么需要集合?它比数组强在哪? 🤔🚀
相比数组,集合主要有这些优势:
- 动态大小 <📏➡️<♾️>>:大部分集合的大小是可变的,你可以随时添加或删除元素,不用担心容量问题。
- 丰富的功能 <⚙️>: 集合框架提供了大量现成的方法来操作数据,比如添加、删除、查找、排序、迭代等,比数组方便得多。
- 不同的数据结构 <🗺️>: 集合框架提供了多种数据结构(如列表、集、队列、映射),每种都有不同的特点(如是否有序、是否允许重复),可以根据需求选择最合适的。
- 泛型支持 : 集合天生与泛型结合,保证了类型安全,避免了从集合中取出元素时的强制类型转换和潜在错误。
二、集合框架的核心:接口与实现 <🧱>
Java 集合框架的设计非常优雅,它主要由一系列接口(定义规范)和实现类(提供具体的数据结构和算法)组成。我们写代码时,应该尽量面向接口编程,这样更灵活。
核心接口主要有这几位大佬:
Collection<E>
<🧺>: 单列集合的根接口,定义了所有单列集合(一次存一个元素)的基本操作,如add()
,remove()
,contains()
,size()
,isEmpty()
,iterator()
。它派生出两个主要的子接口:List
和Set
。List<E>
<📝>: 有序的集合(元素按插入顺序排列),允许存储重复的元素。可以把它想象成一个带编号的清单,可以根据索引(编号)精确访问。Set<E>
<🚫>: 无序(通常不保证顺序)的集合,不允许存储重复的元素。就像一个独特的邮票收藏册 ,每张邮票都是独一无二的。Queue<E>
<🚶♀️➡️🚶♂️>: 队列接口,通常遵循先进先出(FIFO)的原则(也有例外,如优先队列)。就像排队买票 <🎫>,先来的先买。Map<K, V>
<🔑➡️<🎁>>: 映射接口,存储的是键值对 (Key-Value Pair)。注意⚠️:Map
不直接继承Collection
接口,它自成一派,但通常被认为是集合框架的一部分。Key 必须唯一,Value 可以重复。就像一本字典 📖,通过唯一的“单词”(Key)可以查到对应的“解释”(Value)。
接下来,我们详细看看最常用的 List
, Set
, Map
及其主要实现。
三、List
接口:有序,可重复 <📝>
特点:存入和取出的顺序一致,可以包含相同的元素。
常用实现类:
ArrayList<E>
<🧱>:- 底层:基于动态数组实现。
- 优点👍:查询(根据索引
get()
)速度快⚡️(随机访问快)。 - 缺点👎:增删(
add()
/remove()
,尤其是在中间位置)速度相对较慢🐢,因为可能需要移动大量元素。 - 适用场景🎯:查找多、增删少的情况。最常用的 List 实现。
LinkedList<E>
<🔗>:- 底层:基于双向链表实现。
- 优点👍:增删(尤其是在首尾)速度快🚀,不需要移动元素,只需修改指针。
- 缺点👎:查询(根据索引
get()
)速度相对较慢🐌,需要从头或尾开始遍历链表。 - 适用场景🎯:增删多、查找少的情况。它也实现了
Queue
接口,常被用作队列或栈。
代码示例 (ArrayList
):
import java.util.ArrayList;
import java.util.List;public class ListDemo {public static void main(String[] args) {// 创建一个存储 String 的 ArrayList (面向接口编程)List<String> names = new ArrayList<>(); // new// 添加元素names.add("Alice"); // 索引 0names.add("Bob"); // 索引 1names.add("Charlie"); // 索引 2names.add("Bob"); // 允许重复System.out.println("Names list: " + names); // 输出保持添加顺序// 获取元素 (按索引)String secondName = names.get(1); // 获取索引为 1 的元素System.out.println("Second name: " + secondName); // Bob// 修改元素names.set(3, "David"); // 修改索引为 3 的元素System.out.println("After modification: " + names);// 删除元素names.remove(0); // 删除索引为 0 的元素System.out.println("After removing first element: " + names);// 获取大小System.out.println("Current size: " + names.size());// 遍历 (增强 for)System.out.print("Iterating through names: ");for(String name : names) {System.out.print(name + " ");}System.out.println();}
}
四、Set
接口:无序 (通常),不重复 <🚫>
特点:不能包含重复的元素。大部分实现不保证元素的存取顺序。
常用实现类:
HashSet<E>
<🧺><#️⃣>:
- 底层:基于哈希表 (HashMap 实现)。
- 优点👍:添加、删除、查找(
contains()
)速度非常快⚡️(平均 O(1))。 - 缺点👎:不保证元素的顺序。
- 要求:存入
HashSet
的元素必须正确重写hashCode()
和equals()
方法。 - 适用场景🎯:需要快速去重或快速判断元素是否存在,且不关心顺序。最常用的 Set 实现。
代码示例 (HashSet
):
import java.util.HashSet;
import java.util.Set;public class HashSetDemo {public static void main(String[] args) {// 创建一个存储 Integer 的 HashSet (面向接口编程)Set<Integer> uniqueNumbers = new HashSet<>(); // new// 添加元素uniqueNumbers.add(5);uniqueNumbers.add(10);uniqueNumbers.add(5); // 尝试添加重复元素 5uniqueNumbers.add(15);uniqueNumbers.add(10); // 尝试添加重复元素 10// 输出 Set,重复元素自动被忽略,顺序不一定是添加顺序System.out.println("Unique numbers set: " + uniqueNumbers); // 可能输出 [5, 10, 15] 或其他顺序// 检查是否包含元素boolean hasTen = uniqueNumbers.contains(10);System.out.println("Set contains 10? " + hasTen); // true// 删除元素uniqueNumbers.remove(5);System.out.println("After removing 5: " + uniqueNumbers);System.out.println("Current size: " + uniqueNumbers.size()); // 2// 遍历 (顺序不保证)System.out.print("Iterating through the set: ");for(Integer num : uniqueNumbers) {System.out.print(num + " ");}System.out.println();}
}
LinkedHashSet<E>
<🔗><#️⃣>:
- 底层:基于哈希表和双向链表。
- 优点👍:既有
HashSet
的快速查找 (O(1)),又能保持元素的插入顺序 <➡️>!遍历时会按照添加的顺序输出。 - 缺点👎:性能略低于
HashSet
(因为维护链表的额外开销),内存占用也稍大。 - 要求:同样需要元素正确重写
hashCode()
和equals()
。 - 适用场景🎯:需要去重,同时希望保持元素添加时的顺序。
代码示例 (LinkedHashSet
):
import java.util.LinkedHashSet;
import java.util.Set;public class LinkedHashSetDemo {public static void main(String[] args) {// 创建 LinkedHashSet,保持插入顺序Set<String> orderedUniqueNames = new LinkedHashSet<>(); // neworderedUniqueNames.add("Charlie");orderedUniqueNames.add("Alice");orderedUniqueNames.add("Bob");orderedUniqueNames.add("Alice"); // 重复的 Alice 被忽略// 输出时会保持添加顺序!System.out.println("Ordered unique names: " + orderedUniqueNames);// Output: Ordered unique names: [Charlie, Alice, Bob]}
}
TreeSet<E>
<🌳>:
- 底层:基于红黑树 (TreeMap 实现)。
- 优点👍:元素会自动排序!可以按照元素的自然顺序(元素需实现
Comparable
接口)或者指定的比较器(创建TreeSet
时传入Comparator
)进行排序。 - 缺点👎:增删查的速度略慢于
HashSet
(O(log n))。 - 要求:存入
TreeSet
的元素必须是可比较的。 - 适用场景🎯:需要去重的同时保持元素有序。
代码示例 (TreeSet
):
import java.util.Set;
import java.util.TreeSet;public class TreeSetDemo {public static void main(String[] args) {// 创建 TreeSet,元素会自动排序Set<Integer> sortedNumbers = new TreeSet<>(); // newsortedNumbers.add(50);sortedNumbers.add(20);sortedNumbers.add(80);sortedNumbers.add(20); // 重复的 20 被忽略// 输出时元素是排序好的!System.out.println("Sorted unique numbers: " + sortedNumbers);// Output: Sorted unique numbers: [20, 50, 80]}
}
五、Map
接口:键值对存储 <🔑➡️<🎁>>
特点:存储的是 Key-Value 对,Key 必须唯一,Value 可以重复。通过 Key 可以快速查找到对应的 Value。
常用实现类:
HashMap<K, V>
<🧺><#️⃣>:
-
底层:基于哈希表。
-
优点👍:增删查(根据 Key)速度极快⚡️(平均 O(1))。
-
缺点👎:不保证键值对的存储顺序。
-
要求:Key 必须正确重写
hashCode()
和equals()
。 -
允许 Key 和 Value 为
null
(Key 只能有一个null
)。 -
适用场景🎯:需要快速 Key-Value 查找,不关心顺序。最常用。
-
LinkedHashMap<K, V>
<🔗><#️⃣>:- 底层:基于哈希表和双向链表。
- 优点👍:既有
HashMap
的快速查找,又能保持键值对的插入顺序 <➡️>(或访问顺序,构造时可指定)。 - 缺点👎:性能略低于
HashMap
,内存占用稍大。 - 要求:Key 同样需要
hashCode()
和equals()
。 - 适用场景🎯:需要保持插入顺序的映射关系,如实现LRU缓存(使用访问顺序)。
-
TreeMap<K, V>
<🌳>:- 底层:基于红黑树。
- 优点👍:键值对会根据 Key 自动排序!
- 缺点👎:增删查速度略慢(O(log n))。
- 要求:Key 必须是可比较的。
- 不允许 Key 为
null
。 - 适用场景🎯:需要按 Key 排序的映射关系。
-
Hashtable<K, V>
<🔒><#️⃣>:- 底层:也是基于哈希表。
- 特点:线程安全!所有方法都是
synchronized
的。 - 缺点👎:因为所有方法都加锁,并发性能很差 <🐢>。现在基本不推荐使用。
- 不允许 Key 或 Value 为
null
<🚫>。 - 替代方案💡:需要线程安全的 Map,优先考虑
<font color="purple">ConcurrentHashMap</font>
(来自java.util.concurrent
包),它提供了更好的并发性能。
(HashMap 和 TreeMap 示例省略,见上一版本)
六、 集合工具类:Collections
<🛠️>
别和 Collection
接口搞混了!Collections
(带 s) 是一个工具类,里面全是 static
方法,用来方便地操作集合。
一些常用方法:
Collections.sort(List<T> list)
: 对List
进行排序 <📊>。Collections.reverse(List<?> list)
: 反转List
中元素的顺序 <🔄>。Collections.shuffle(List<?> list)
: 随机打乱List
中元素的顺序 <🔀>。Collections.max(Collection<? extends T> coll)
/min(...)
: 找到集合中的最大/最小值 <🥇><🥉>。Collections.frequency(Collection<?> c, Object o)
: 计算指定元素在集合中出现的次数 <🔢>。Collections.synchronizedList/Set/Map(...)
: 返回指定集合的线程安全版本 <🔒> (性能不如java.util.concurrent
包下的类)。Collections.unmodifiableList/Set/Map(...)
: 返回指定集合的只读视图 <🚫>✍️。
代码示例:
import java.util.ArrayList;
import java.util.Collections; // 导入工具类
import java.util.List;public class CollectionsUtilDemo {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>();numbers.add(5);numbers.add(1);numbers.add(8);numbers.add(3);System.out.println("Original list: " + numbers);// 排序Collections.sort(numbers);System.out.println("Sorted list: " + numbers);// 反转Collections.reverse(numbers);System.out.println("Reversed list: " + numbers);// 查找最大值Integer max = Collections.max(numbers);System.out.println("Maximum value: " + max);}
}
七、 别忘了迭代器 (Iterator
) <🔍>
迭代器是遍历所有 Collection
(List, Set, Queue) 的标准、通用方式。虽然增强型 for
循环更简洁,但迭代器允许你在遍历过程中安全地删除元素(使用 iterator.remove()
)。
(迭代器代码示例省略,见上一版本)
八、总结:选择合适的容器 🏁
Java 集合框架提供了一套丰富、灵活、高效的数据容器。选择时主要考虑:
- 是否有序? (
List
有序, 大部分Set
/Map
无序,LinkedHashSet
/LinkedHashMap
插入有序,TreeSet
/TreeMap
排序) - 是否允许重复? (
List
允许,Set
不允许) - 存储结构? (单个元素用
List
/Set
, 键值对用Map
) - 性能需求? (查找为主选
ArrayList
/HashSet
/HashMap
, 增删为主选LinkedList
, 需要排序选TreeSet
/TreeMap
) - 是否需要线程安全? (优先考虑
ConcurrentHashMap
等java.util.concurrent
包下的类)
核心原则:面向接口编程!始终使用泛型!根据需求选择最合适的实现类。
九、练练手,检验成果!✏️🧠
检验一下学习成果吧!
⭐ 选择与应用 ⭐
- 如果你需要存储用户访问网站的页面顺序(URL 字符串),并且可能会频繁在列表开头添加新的访问记录(最新的访问总在最前面),你会选择
ArrayList<String>
还是LinkedList<String>
?为什么? - 你需要存储一个班级所有学生的学号 (String),要求不能重复,并且希望能够快速检查某个学号是否已经存在,对顺序没有要求。选择哪个
Set
实现? - 你想记录每个单词 (String) 在一篇文章中出现的次数 (Integer)。选择哪个
Map
实现最合适? - 新增:如果第3题中,你希望输出单词及其次数时,单词能按照字母顺序排列,应该选择哪个
Map
实现? - 新增:你需要一个线程安全的
Map
来存储缓存数据,应该优先选择哪个类?
⭐ 工具类与遍历 ⭐
- 创建一个
ArrayList<Integer>
,添加一些数字,然后使用Collections.sort()
对其排序,并使用Collections.reverse()
将其反转,最后打印结果。 - 使用迭代器遍历一个
HashSet<String>
,并在遍历过程中安全地删除所有长度小于 5 的字符串。
⭐ 概念辨析 ⭐
Collection
和Collections
有什么区别?- 为什么
HashMap
的 Key 需要正确重写hashCode()
和equals()
方法?如果只重写equals()
而不重写hashCode()
会有什么问题? - 新增:
ArrayList
和Vector
有什么主要区别?为什么现在很少推荐使用Vector
?
十、参考答案 ✅💡
⭐ 选择与应用答案 ⭐
-
选择
LinkedList
。- 原因:需要在列表开头进行频繁的添加操作。
LinkedList
在首部添加元素的时间复杂度是 O(1),非常快。而ArrayList
在开头添加元素需要将所有现有元素向后移动,时间复杂度是 O(n),效率低。
- 原因:需要在列表开头进行频繁的添加操作。
-
选择
HashSet<String>
。- 原因:需求是去重 (
Set
特性),快速检查是否存在 (HashSet
提供 O(1) 的contains()
操作),且不关心顺序。HashSet
完美符合这些要求。
- 原因:需求是去重 (
-
选择
HashMap<String, Integer>
。- 原因:需要存储单词 (Key) 到出现次数 (Value) 的映射关系 (
Map
功能)。单词 (Key) 是唯一的。通常查找某个单词的次数(get(word)
)和更新次数(put(word, count + 1)
)需要快,HashMap
提供 O(1) 的平均性能。对单词的存储顺序通常不关心。
- 原因:需要存储单词 (Key) 到出现次数 (Value) 的映射关系 (
-
选择
TreeMap<String, Integer>
。- 原因:
TreeMap
会根据 Key (String
) 的自然顺序(字母顺序)自动对键值对进行排序。
- 原因:
-
优先选择
ConcurrentHashMap<K, V>
(来自java.util.concurrent
包)。- 原因:
ConcurrentHashMap
提供了高效的线程安全机制(如分段锁或 CAS),并发性能远好于使用全局锁的Hashtable
或Collections.synchronizedMap()
。
- 原因:
⭐ 工具类与遍历答案 ⭐
-
排序与反转 List:
import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Arrays; // 方便初始化public class SortReverseDemo {public static void main(String[] args) {List<Integer> numbers = new ArrayList<>(Arrays.asList(5, 1, 8, 3, 2));System.out.println("Original list: " + numbers);Collections.sort(numbers); // 排序System.out.println("Sorted list: " + numbers);Collections.reverse(numbers); // 反转System.out.println("Reversed list: " + numbers);} }
-
使用迭代器安全删除:
import java.util.HashSet; import java.util.Iterator; import java.util.Set;public class IteratorRemoveDemo {public static void main(String[] args) {Set<String> words = new HashSet<>();words.add("Java");words.add("is");words.add("fun");words.add("and");words.add("powerful");System.out.println("Original set: " + words);// 必须使用迭代器进行遍历中的删除操作Iterator<String> iterator = words.iterator();while (iterator.hasNext()) {String word = iterator.next();if (word.length() < 5) {// 安全删除当前元素iterator.remove(); // 使用迭代器的 remove() 方法System.out.println("Removed: " + word);}}// 不能在增强 for 循环中直接调用 words.remove(word),会抛 ConcurrentModificationExceptionSystem.out.println("Set after removal: " + words);} }
⭐ 概念辨析答案 ⭐
-
Collection
vsCollections
:Collection
: 是一个 接口 <📝>,单列集合的根。Collections
: 是一个 工具类 <🛠️>,提供操作集合的static
方法。
-
为什么
HashMap
Key 需要hashCode()
和equals()
: (答案同上一版本,此处省略) -
ArrayList
vsVector
:- 主要区别:
Vector
是线程安全的,它的所有方法都使用synchronized
修饰。ArrayList
是非线程安全的。此外,Vector
是 Java 早期 (JDK 1.0) 就存在的类,而ArrayList
是在集合框架 (JDK 1.2) 中引入的。Vector
的默认扩容大小通常是翻倍,而ArrayList
通常是增长 50%。 - 为什么少用
Vector
: 因为其全局同步导致性能低下 <🐢>,在不需要线程安全的场景下完全没必要用它(用ArrayList
更快)。而在需要线程安全的场景下,有性能更好的替代品,如使用Collections.synchronizedList()
包装ArrayList
(虽然锁粒度仍然较大),或者直接使用java.util.concurrent
包下的CopyOnWriteArrayList
(适用于读多写少的场景)。因此,Vector
现在基本被视为遗留类,在新代码中很少推荐使用。
- 主要区别:
集合框架是 Java 中使用极其频繁的部分,掌握好它对日常开发至关重要!希望这篇笔记能帮你理清思路。如果觉得有帮助,别忘了 点赞👍、收藏⭐、关注 哦! 😉
相关文章:
Java 进阶--集合:告别数组的“僵硬”,拥抱灵活的数据容器
作者:IvanCodes 发布时间:2025年5月1日🫡 专栏:Java教程 大家好!👋 还记得我们上次聊的数组 (Array) 吗?它很基础,性能也不错,但有个致命的缺点:长度一旦定…...
Python 数据智能实战 (6):用户评论深度挖掘
写在前面 —— 从繁杂评论到精准洞察:主题发现与情感趋势分析,驱动产品优化与体验提升 在上篇内容中,我们学习了如何利用 LLM 提升用户分群的精度,以及如何超越传统购物篮分析,挖掘商品间的语义关联。今天,我们将聚焦于电商领域 价值密度最高 的非结构化数据之一——用…...
podman/docker国内可用的docker镜像源(2025-05)
一、添加Docker国内镜像 1、修改 /etc/docker/daemon.json 设置 registry mirror,具体命令如下: sudo vim /etc/docker/daemon.json <<EOF {"registry-mirrors": ["https://docker.1ms.run","https://docker.xuanyuan.me",&q…...
机器人--底盘
机器人底盘 底盘是机器人传感器和机器人主机的载体,也是移动机器人的基本形式。移动机器人通常可以采用轮式和足式进行移动。 也就是机器人底盘可以分为轮式底盘和足式底盘。 足式底盘控制复杂,这里只讨论轮式底盘。 底盘运动学模型 轮式机器人底盘按…...
Seata服务端同步提交事务核心源码解析
文章目录 前言一、doGlobalCommit(同步提交)2.1、closeAndClean()2.2、changeGlobalStatus2.3、doGlobalCommit2.3.1、findGlobalSession 总结 前言 本篇介绍Seata服务端TC如何驱动RM提交事务。 一、doGlobalCommit(同步提交) doG…...
2025五一杯B题五一杯数学建模思路代码文章教学: 矿山数据处理问题
完整内容请看文章最下面的推广群 问题1. 根据附件1中的数据和,建立数学模型,对数据A进行某种变换,使得变换后的结果与数据尽可能接近。计算变换后的结果与数据的误差,并分析误差的来源(如数据噪声、模型偏差等…...
C++11新特性_自动类型推导
decltype 和 auto 均为 C 里用于类型推导的关键字,不过它们在使用方式、推导规则和应用场景上存在显著差异。下面为你详细介绍它们的区别: 1. 推导依据 auto:它依据变量的初始化表达式来推导类型。也就是说,auto 定义的变量必须有…...
【AI论文】ReasonIR:为推理任务训练检索器
摘要:我们提出了ReasonIR-8B,这是第一个专门针对一般推理任务进行训练的检索器。 现有的检索器在推理任务上表现出的收益有限,部分原因是现有的训练数据集侧重于与直接回答它们的文档相关的简短事实查询。 我们开发了一个合成数据生成管道&am…...
嵌入式AI还是一片蓝海
发现其实还是挺多人关注嵌入式和人工智能交叉领域的,随便一个问题,浏览量就27万了,但是这方面的内容确实少得可怜……所以干脆我自己来补点干货。 推荐一本最近很热门的新书——《边缘人工智能:用嵌入式机器学习解决现实问题》。 …...
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(13): ておきます ています & てあります
日语学习-日语知识点小记-构建基础-JLPT-N4阶段(13): ておきます &ています & てあります 。 1、前言(1)情况说明(2)工程师的信仰 2、知识点(1)&#x…...
CMake管理外部依赖的模块
在 CMake 中,FetchContent 和 ExternalProject 都是管理外部依赖的模块,但它们的 设计目标、使用场景和执行时机 有本质区别。以下通过对比表格、代码示例和场景分析详细说明它们的区别。 核心区别对比表 特性FetchContentExternalProject执行阶段配置阶…...
[计算机科学#7]:CPU的三阶段,取指令、解码、执行
【核知坊】:释放青春想象,码动全新视野。 我们希望使用精简的信息传达知识的骨架,启发创造者开启创造之路!!! 内容摘要:本文详细介绍了CPU的工作原理,包括其结构…...
向量数据库和关系型数据库的区别,优点,缺点和典型应用场景
向量数据库与关系型数据库的全面对比 向量数据库和关系型数据库是两种截然不同的数据管理系统,各自针对特定的数据模型和查询模式进行了优化。随着人工智能和大数据技术的发展,向量数据库作为新兴的数据库类型,在处理非结构化数据方面展现出…...
《跨越边界:探索跨端框架中通用状态管理方案设计》
一款应用往往需要在多个终端,如Web、移动端、桌面端等同时运行,以满足用户多元化的使用场景。在这复杂的跨端开发领域中,状态管理堪称关键枢纽,直接关乎应用的性能、稳定性以及开发与维护的效率。如何设计一套通用的状态管理方案&…...
PHP之CURL通过header传参数及接收
一、传参数之冒号 注意一点,这里的header数据不是KV结构,而是一个一维数组。 看清楚,注意一点,是这样的结构: $ch curl_init(); $headers [X-Custom-Header: value123,Authorization: Bearer your_token_here // …...
【C++】brpc安装
brpc安装教程 环境:Ubuntu24.04 1 简单安装 即安装到系统环境下,依赖也是依赖apt安装。 官方参考教程 依赖准备 安装依赖: sudo apt-get install -y git g make libssl-dev libgflags-dev libprotobuf-dev libprotoc-dev protobuf-com…...
从0开始的c++知识讲解之字符串(1)
作者作为新手,对于知识的讲解也是边输出内容也是边学习,如有缺陷,请多海涵,但同样,我会帮助你从新手视角看到新手的疑惑,并帮助你解决此疑惑 一,开宗明义,立意先行 string在C里有可…...
Linux 第六讲 --- 工具篇(一)yum/apt与vim
前言: 经过前五讲对Linux基础指令与权限系统的系统学习,相信你已经能在命令行中自如地穿梭于文件丛林,精准调配权限密钥。但真正的Linux玩家,绝不会止步于基础操作的重复劳作。 从今天起,我们将打开Linux的"瑞士…...
xml 和 yaml 的区别
XML 和 YAML/YML 是两种常用的数据序列化格式,用于存储和读取结构化数据。以下是它们的核心区别和使用方法: 1. 格式特性对比 特性XMLYAML/YML语法复杂度标签嵌套,结构严格缩进分层,更简洁可读性较低(冗余标签&#…...
1.67g 雨晨 22635.5305 Windows 11 企业版 23H2 极速增强版
五一特别制作 (主要更新简述) 全程由最新YCDISM2025装载制作 1、可选功能: 添加: Microsoft-Windows-LanguageFeatures-Basic-en-us-Package Microsoft-Windows-LanguageFeatures-OCR-en-us-Package 2、功能增强&a…...
【C++】类和对象(中)——默认成员函数详解(万字)
文章目录 上文链接类的默认成员函数1. 构造函数(1) 什么是构造函数(2) 构造函数的使用 2. 析构函数(1) 什么是析构函数(2) 析构函数的使用(3) 小练习 3. 拷贝构造函数(1) 什么是拷贝构造函数(2) 拷贝构造函数的使用 4. 赋值运算符重载(1) 运算符重载(2) 运算符重载的简单应用(3…...
Ubuntu18 登录界面死循环 Ubuntu进不了桌面
今天碰到这个问题,真是把我恶心到了 网上很多方法都不靠谱,最后我还是自己摸索出一个方法 先进入终端 开机后在登陆界面按下shift ctrl F1(或者F2,一直按)进入tty命令行终端登陆后输入(本人的用户名为hpÿ…...
caffe适配cudnn9.6.0(ai修改代码踩坑)
caffe适配cudnn:https://github.com/dyc2424748461/caffe (测试一下,成没成,反正我看到它用gpu了😶) 因为突发奇想,想要玩easymocap,先是简单使用media跑通了一下,然后过…...
【MySQL数据库】视图
1,视图的基本介绍 视图是一个虚拟表,其内容由查询定义。与真实表一样的是,视图包含带有名称的列和行数据;与真实表不一样的是,视图本身并不在数据库中存储数据。视图的数据变化会影响到基表,基表的数据变化…...
Linux日常使用与运维的AI工具全景调研:效率革命的终极指南
Linux日常使用与运维的AI工具全景调研:效率革命的终极指南 引言:当Linux遇上AI,运维世界正在发生什么? 作为一名Linux系统管理员,你是否还在为以下问题困扰: 深夜被报警短信惊醒,却要手动排查复杂的系统故障?面对海量日志文件,像大海捞针一样寻找关键错误信息?重复…...
Linux——线程(3)线程同步
一、线程同步的引入 通过上面的抢票系统我们发现,有的线程,进行工作(挂锁),当其马上结束工作(解锁),发现外面有很多线程在排队等着加锁执行任务,这个线程解锁后就立马给…...
Redis实现分布式锁
分布式锁是分布式系统中解决资源竞争问题的重要机制。Redis凭借其高性能和原子性操作,成为实现分布式锁的热门选择。本文将详细介绍如何使用Java和Redis实现分布式锁,并重点讲解如何通过Lua脚本保证锁操作的原子性。 一、分布式锁的基本要求 一个可靠的…...
JavaScript如何实现类型判断?
判断一个数据的类型,常用的方法有以下几种: typeofinstanceofObject.prototype.toString.call(xxx) 下面来分别分析一下这三种方法各自的优缺点 typeof typeof的本意是用来判断一个数据的数据类型,所以返回的也是一个数据类型。但是会遇到下…...
Spring MVC 与 FreeMarker 整合
以下是 Spring MVC 与 FreeMarker 整合的详细步骤,包含配置和代码示例: 1. 添加依赖 在 pom.xml 中引入 Spring MVC 和 FreeMarker 的依赖(以 Maven 为例): <!-- Spring Web MVC --> <dependency><gr…...
设计模式简述(十五)观察者模式
观察者模式 描述基本组件使用 描述 观察者模式,顾名思义就是一个对象观察着其他对象,一旦被观察的对象发生变化时,观察者对象也要做出相应动作。 其中,被观察者持有观察者的引用。由观察者主动注入被观察者内(有点像…...
用手机相册教我数组概念——照片分类术[特殊字符][特殊字符]
目录 前言一、现实场景1.1 手机相册的照片管理1.2 照片分类的需求 二、技术映射2.1 数组与照片分类的对应关系2.2 数组索引与照片标签的类比 三、知识点呈现3.1 数组的基本概念3.2 数组在编程中的重要性3.3 数组的定义与初始化3.4 数组的常见操作(增删改查ÿ…...
字符串格式漏洞-[第五空间2019 决赛]PWN5
之前其实也写了一篇,现在再来看。又有新的收获了,于是记录一下 前置知识 格式化字符串漏洞详解-CSDN博客 讲得很清楚,我就不照猫画虎了 实践 main函数 首先先办法泄露我们输入的地址 from pwn import * elfpathlevel0 # ioprocess(elfp…...
数据结构学习之顺序表
在C语言学习到一定阶段之后,接下来我们就进入到了数据结构的部分内容。 目录 数据结构与线性表 顺序表 顺序表分类: 接下来我们要写一段代码实现动态顺序表。 首先我们需要准备三个文件: 1.接下来我们要定义一个数据表 2.当创建号我们的…...
AWS CloudFront全球加速利器:解析出海业务的核心优势与最佳实践
对于寻求全球化发展的企业而言,AWS CloudFront凭借其强大的全球基础设施和边缘计算能力,成为加速出海业务的关键工具。本文将深入剖析CloudFront的核心优势,并探讨其如何助力企业突破跨境业务瓶颈,同时符合SEO优化策略,…...
Flowable7.x学习笔记(十六)分页查询我的待办
前言 我的待办具体区分为3种情况,第一个就是办理人指定就是我,我可以直接审批;第二种就是我是候选人,我需要先拾取任务然后再办理;第三种是我是候选组,我需要切换到指定的角色去拾取任务再办理。如果任务已…...
Annotate better with CVAT
WIN10 配置标注环境 WSL + Docker Desktop 安装手册 https://docs.cvat.ai/docs/administration/basics/installation/ hebing@hello:~$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE cvat/ui …...
QML Image 组件详解
目录 引言相关阅读QML Image元素基础知识 项目结构示例解析1. 本地资源图像加载2. 网络图像加载3. 图像填充模式 应用主结构 总结下载链接 引言 本文将介绍QML中Image元素的基本用法和关键特性,包括加载本地资源图像、处理网络图像、以及调整图像的填充模式。通过一…...
BOFZ 緩衝區溢出shell脚本檢測工具
地址:https://github.com/MartinxMax/bofz BOFZ BOFZ 是一款簡單的緩衝區溢出掃描器,旨在檢測指定可執行文件中的緩衝區溢出漏洞。 此工具可用於快速測試應用程序或二進制文件中是否存在常見的安全缺陷,特別是那些由於對用戶輸入處理時邊界檢查不當而引…...
【Dify系列教程重置精品版】第五章:Dify配置Ollama
上一章我们在Dify上尝试配置了“月之暗面”。这一章我们在Dify上配置另一个模型“Ollama”。 什么是ollama呢?简单来说:它允许用户在个人计算机或服务器上快速部署和管理多种开源大语言模型,如 Llama3、Phi3、Gemma2 等,而无需依赖昂贵的云服务或专业的技术背景。 反正就是…...
RISC-V AIA SPEC学习(四)
第五章 Interrupts for Machine andSupervisor Levels 核心内容 1.主要中断类型与默认优先级: 定义了机器级别(M-level)和监管者级别(S-level)的标准中断类型(如MEI、SEI、MTI等)。默认优先级规则:本地中断(如软件/定时器)优先级高于外部中断,RAS事件(如低/高…...
Leetcode刷题报告2——双指针法
文章目录 前言[15. 三数之和](https://leetcode.cn/problems/3sum/)题干题解知识点总结 [42. 接雨水](https://leetcode.cn/problems/trapping-rain-water/)题干题解 前言 这部分总共是4道题,我就挑两道比较典型的题写一下博客吧。 双指针法的核心思路是通过合理的…...
线段树原理和代码详解
目录 线段树维护的信息类型 线段树的结构 线段树的初始化 线段树的功能: 单点修改,区间查询 区间修改,区间查询 以下内容均为个人见解,如有不足还请指出,作者会及时修改! 期待大家的点赞、收藏、评论&…...
xray-poc编写示例
禁止未授权扫描和测试行为!!! 1. SQL 时间盲注检测 (Time-Based Blind SQLi) name: generic/time-based-sqli rules:- method: GETpath: "/product?id1 AND (SELECT 1 FROM (SELECT SLEEP(5))a)--"expression: |response.status…...
[2-01-01].前端开发工具
前端学习大纲 一、VsCode: 1.1、下载地址 https://code.visualstudio.com/ 1.2.插件安装 为方便后续开发,建议安装如下插件 1.3.创建项目 先创建一个空的文件夹,如project_xxxx。然后打开vscode,再在vscode里面选择 File -> Open Fol…...
自动化实现web端Google SignUp——selenium
案例:自动化获取Google注册页面——selenium 前言 提示:通过案例掌握selenium语法 涉及技术:Python Selenium 在本文中,我们将通过一个实际案例来学习如何使用Selenium自动化工具模拟Google账号注册流程。这个案例涵盖了Selen…...
如何阅读GitHub上的深度学习项目
一、前期准备:构建知识基础 1. 必备工具与环境 开发工具: IDE:VS Code(推荐,轻量化插件丰富,如 Python、PyTorch 插件)、PyCharm(适合大型项目)。版本控制:…...
【LeetCode 热题 100】3.无重复字符的最长子串:详解滑动窗口解法
📌 原题链接:Longest Substring Without Repeating Characters 📖 一、题目描述 给定一个字符串 s,请你找出其中不含有重复字符的最长子串的长度。 示例: 输入: s "abcabcbb" 输出: 3 解释: 最长不重复子…...
Android12 Rom定制设置默认语言为中文
Android12 Rom定制设置默认语言为中文 1.前言: 最近在做客制化定制时需要默认语言为中文,而且可以切换输入法,之前讲解过在ROM中如何设置默认输入法,这里就不展开了,其实这个需求很简单,就是调试的时候发现…...
【设计模式】GoF设计模式之备忘录模式(Memento Pattern)
设计模式之备忘录模式 Memento Pattern V1.0核心概念角色代码示例程序运行结果代码讲解 适用场景 V1.0 核心概念 备忘录模式的核心是定义一个备忘录类(Memento),这个类的实例能够表示发起人类(Originator)的一种状态…...
springboot分层打包,减少重复构建和传输的开销
在 Spring Boot 中,分层打包(Layered Packaging) 是一种优化策略,特别针对 容器化部署(如 Docker) 的场景设计。它的核心思想是将应用的不同部分(依赖、资源、代码等)划分为独立的层…...