【八股战神篇】Java集合高频面试题
专栏简介
八股战神篇专栏是基于各平台共上千篇面经,上万道面试题,进行综合排序提炼出排序前百的高频面试题,并对这些高频八股进行关联分析,将每个高频面试题可能进行延伸的题目再次进行排序选出高频延伸八股题。面试官都是以点破面从一个面试题不断深入,目的是测试你的理解程度。本专栏将解决你的痛点,助你从容面对。本专栏已更新Java基础高频面试题、Java集合高频面试题,后续会更新JUC、JVM、MySQL、JVM、Redis、操作系统、计算机网络、设计模式、场景题等,计划在七月前更新完毕(赶在大家高频面试前)点此链接订阅专栏“八股战神篇”
一 常见的集合类型有哪些?
Java 集合框架分为单列集合和双列集合两大类。
首先是单列集合,它以 Collection 为核心接口,主要分为三种:
第一种是 List,用于存储有序且可重复的元素,比如 ArrayList 基于动态数组,访问快但插入删除慢;LinkedList 基于双向链表,插入删除快但访问慢;Vector 是线程安全的老版本实现。
第二种是 Set,用于存储无序且不可重复的元素,比如 HashSet 基于哈希表,查找快但无序;LinkedHashSet 保留插入顺序;TreeSet 基于红黑树,按顺序存储。
第三种是 Queue,用于队列操作,比如 PriorityQueue 基于堆实现按优先级处理,ArrayDeque 是双端队列支持栈和队列操作。
接下来是双列集合,它以 Map 为核心接口,用于存储键值对,比如:HashMap 基于哈希表,键无序且查找快;LinkedHashMap 保留插入顺序;TreeMap 基于红黑树,按键的自然顺序排序;Hashtable 是线程安全的老版本实现。
延伸
1,集合体系结构图
为了更好理解,可以参考以下简单的结构:
Collection|-- List| |-- ArrayList| |-- LinkedList|-- Set| |-- HashSet| |-- TreeSet|-- Queue|-- LinkedList|-- PriorityQueue
Map|-- HashMap|-- TreeMap|-- LinkedHashMap
2,集合的选择
-
如果需要快速查询:使用
HashSet
或HashMap
。 -
如果需要排序:使用
TreeSet
或TreeMap
。 -
如果需要保证插入顺序:使用
LinkedHashSet
或LinkedHashMap
。 -
如果需要动态大小的数组:使用
ArrayList
。 -
如果需要频繁插入删除:使用
LinkedList
。
3,如果只有单列集合,没有双列集合,会发生什么?
双列集合最核心的特性是以键值对形式存储数据,每个键唯一且对应一个值。如果没有双列集合,会导致:
需要手动管理键值关系: 开发者需要用单列集合(如List)分别存储键和值,自己维护它们的对应关系,增加了开发复杂度。
效率低下: 查找某个键对应的值需要遍历整个键的集合,而不是像Map一样通过哈希或排序快速定位。
二 ArrayList和LinkedList的区别?
ArrayList
和 LinkedList
是 Java 中常用的两个 List
接口实现类。它们在底层数据结构和性能上有很大的区别,各有优缺点,适用于不同的场景。以下是它们详细的区别。
第一点是底层实现不同
ArrayList:基于 动态数组 实现,元素连续存储,支持通过索引直接访问元素(随机访问),数组容量不足时会进行 动态扩容。
LinkedList:基于 双向链表 实现,每个节点包含一个数据部分和两个指针,分别指向前一个和后一个节点,不支持通过索引直接访问,需要通过遍历找到对应位置的元素。
第二点是访问性能不同
ArrayList:随机访问性能优越,时间复杂度为 O(1),因为可以直接通过索引访问,适合频繁读取元素的场景,例如:根据索引获取数据。
LinkedList:随机访问性能较差,时间复杂度为 O(n),需要从头或尾部开始遍历才能找到对应的元素,不适合频繁读取或按索引访问元素的场景。
第三点是插入和删除性能不同
ArrayList:插入或删除操作(非尾部)可能涉及大量数据的移动,时间复杂度为 O(n),删除或插入元素时,所有后续元素都需要移动,尤其是在列表中间插入或删除元素时,在 尾部插入 元素的时间复杂度通常是 O(1),但当数组容量不足时会触发 扩容,导致性能下降。
LinkedList:插入或删除操作性能更优(非索引访问场景),时间复杂度为 O(1),只需调整链表指针即可,但如果通过索引访问位置后再插入或删除,则时间复杂度为 O(n),适合频繁在列表头部或中间插入和删除元素的场景。
第四点是扩容效率的不同
ArrayList:插入时,如果空间不足需要扩容,扩容会新建一个更大的数组,并将旧数据复制过去,影响性能。
LinkedList:没有容量的概念,插入时只需更新节点指针,不涉及扩容操作。
第五点是内存使用效率的不同
ArrayList:内存利用率较高,仅存储实际数据,数组容量不足时会扩容(默认扩容为原容量的 1.5 倍),可能导致一定的内存浪费,扩容操作需要复制整个数组,会消耗时间和内存。
LinkedList:内存开销较大,每个节点需要额外存储两个指针(prev
和 next
),不会发生扩容问题,因为它是基于链表实现的,当数据量较大时,链表的额外指针开销可能显著增加内存使用。
第六点是使用场景的不同
场景 | 选择 |
---|---|
需要频繁按索引访问元素 | ArrayList |
需要频繁在中间或两端插入、删除元素 | LinkedList |
数据量较大,内存效率要求高 | ArrayList |
数据量不大,频繁插入删除 | LinkedList |
代码示例
1. 随机访问性能对比
import java.util.*;
public class AccessPerformanceTest {public static void main(String[] args) {List<Integer> arrayList = new ArrayList<>();List<Integer> linkedList = new LinkedList<>();
// 初始化数据for (int i = 0; i < 100000; i++) {arrayList.add(i);linkedList.add(i);}
// 测试 ArrayList 的随机访问性能long start = System.nanoTime();arrayList.get(50000);long end = System.nanoTime();System.out.println("ArrayList 随机访问时间: " + (end - start) + " ns");
// 测试 LinkedList 的随机访问性能start = System.nanoTime();linkedList.get(50000);end = System.nanoTime();System.out.println("LinkedList 随机访问时间: " + (end - start) + " ns");}
}
输出示例:ArrayList 随机访问时间: 100 ns
LinkedList 随机访问时间: 20000 ns
2. 插入和删除性能对比
import java.util.*;
public class InsertPerformanceTest {public static void main(String[] args) {List<Integer> arrayList = new ArrayList<>();List<Integer> linkedList = new LinkedList<>();
// 测试在头部插入性能long start = System.nanoTime();for (int i = 0; i < 10000; i++) {arrayList.add(0, i);}long end = System.nanoTime();System.out.println("ArrayList 头部插入时间: " + (end - start) + " ns");
start = System.nanoTime();for (int i = 0; i < 10000; i++) {linkedList.add(0, i);}end = System.nanoTime();System.out.println("LinkedList 头部插入时间: " + (end - start) + " ns");}
}
输出示例:ArrayList 头部插入时间: 50000000 ns
LinkedList 头部插入时间: 2000000 ns
延伸
1,说一下ArrayList的默认大小?它是如何进行扩容的?
在 Java 中,ArrayList 的初始默认容量为 10。
当通过无参构造函数创建一个 ArrayList 时:
ArrayList list = new ArrayList<>();
此时 ArrayList 的容量并未真正分配。
当第一次向 ArrayList 添加元素时(如 list.add(1)),它会分配默认大小为 10 的数组。
当 ArrayList 中的元素数量超过当前容量时,ArrayList 会自动扩容。当数组容量不足时,ArrayList 会将容量扩展为 原容量的 1.5 倍,创建一个新的更大的数组。将原数组中的元素拷贝到新数组中。
示例:
新容量计算公式:
newCapacity = oldCapacity + (oldCapacity >> 1);
初始容量为 10,当元素数量超过 10 时:
第一次扩容:容量从 10 扩展为 15。
第二次扩容:容量从 15 扩展为 22。
依此类推。
2,ArrayList是线程安全的吗?为什么?
ArrayList
不是线程安全的。这是因为 ArrayList
的设计目标是为了在单线程环境下提供高性能,而没有对多线程环境提供内置的线程同步机制。
因为 ArrayList
的底层结构是基于动态数组实现的,它的底层是一个 Object[]
数组,用来存储元素。当需要添加、删除或修改元素时,ArrayList
会直接操作这个数组。
- 在单线程环境下,这种设计性能高效。
- 但在多线程环境下,如果多个线程同时操作同一个
ArrayList
实例,可能会引发数据不一致或异常。
3,ArrayList是否有容量限制?
ArrayList
是 Java 中基于动态数组实现的列表。理论上,ArrayList
的容量限制取决于 JVM 所能分配的最大内存,具体限制与可用的堆内存大小和数组的实现有关。
理论限制:
- 最大容量为
Integer.MAX_VALUE - 8
(即约 2^31 – 1 个元素,约 2.1 billion 个),这是由数组在 JVM 中的实现所决定的。 - 实际限制:受到可用内存的约束,通常在大量数据时可能会触发
OutOfMemoryError
。
三 HashMap的原理是什么?
HashMap 是一种基于哈希表的键值对存储数据结构,它的查找很高效,存储性能较好,被广泛用于高效管理和访问数据。HashMap 的实现基于数组和链表或红黑树,JDK 8之前是数组+链表,JDK 8及之后是数组+链表+红⿊树。接下来我会讲述put方法和get方法的核心逻辑。
put方法:在 HashMap
中,put
方法的核心逻辑是将一个键值对插入到 HashMap
中。其执行流程主要包括以下步骤:
-
计算键的哈希值 根据
hashCode()
方法计算键的哈希值,然后通过哈希值定位键值对应该存储的桶(bucket)。 -
定位桶位置 使用哈希值对数组的长度取模,确定键值对存储的位置。
-
检查冲突(是否有相同哈希值的键)
-
如果桶为空,直接插入键值对。
-
如果桶中已有元素(发生哈希冲突),遍历桶中的链表或树结构:
-
如果找到相同的键(通过
equals
方法判断),则替换旧值为新值。 -
如果未找到相同的键,则将键值对插入到链表末尾或树中。
-
-
-
树化检查 如果链表长度超过阈值(默认 8),链表会转换为红黑树以提高性能。
-
扩容检查 如果插入新键值对后,
HashMap
的实际元素数量超过了负载因子阈值(loadFactor
),会触发扩容(默认将容量翻倍)。
get方法:HashMap
的 get(Object key)
方法用于根据键(key
)获取对应的值(value
)。其核心逻辑是:
-
根据键的
hashCode()
计算哈希值,确定该键所在的桶(bucket
)。 -
遍历该桶中的链表(或红黑树)来查找目标键。
-
如果找到对应的键,返回其对应的值;否则返回
null
。
延伸
1,链表到红黑树的转换条件是什么?
默认链表长度超过 8 时转换为红黑树,减少链表查找时间复杂度(从 O(n) 降到 O(log n))。
2,HashMap为什么采用红黑树而不是采用B+树?
在 HashMap 的实现中,链表长度超过一定阈值(默认 8)时会转换为红黑树,而不是 B+ 树,主要原因如下:
时间复杂度:红黑树是一种平衡二叉搜索树,查找、插入、删除的时间复杂度是 O(log n)。B+ 树虽然在数据库中有优势,但其设计更适合磁盘存储和范围查询,不适合频繁的动态操作。
内存占用:红黑树的内存使用率较低,而 B+ 树由于每个节点存储更多指针,内存开销较大,且不必要。
HashMap 的设计目标:HashMap 的目标是高效查找,而红黑树能很好地满足这一点,并且它与内存结构更契合。B+ 树则更适合大规模外存数据管理。
3,哈希冲突的解决办法有哪些?
拉链法(Chaining):将所有映射到同一哈希桶中的元素存储为链表(或红黑树)。当冲突较少时,链表的查找复杂度为 O(n),当链表转为红黑树后复杂度降为 O(log n)。
开放地址法(Open Addressing):如果一个位置已经被占用,尝试探查其他位置存储冲突的元素。线性探测,依次检查下一个位置。二次探测,按平方步长检查下一个位置。双哈希,使用第二个哈希函数计算探测步长。
再哈希(Rehashing):当哈希表负载因子过高时,扩容并重新计算所有键的哈希值,减少冲突。
四 HashMap如何扩容?
HashMap 在存储过程中可能会遇到哈希冲突,因此需要使用链表或红黑树来解决这些冲突。然而,随着数据量的增加,冲突可能会加剧,导致访问的时间复杂度无法维持在 O(1) 的水平。此时,就需要进行扩容。扩容的过程包括分配新的数组和重新哈希旧数组中的键值对。
HashMap
扩容主要有下面四个核心步骤:
-
触发条件 扩容发生在插入新元素时,如果当前元素数量超过了 阈值,则触发扩容。
-
容量翻倍 扩容时HashMap 会先新建一个数组,新数组的大小是老数组的两倍。
-
重新哈希(Rehashing) 将旧数组中的键值对重新分配到新数组中,重新计算每个键值对在新数组中的位置。在JDK 1.8 及之后对扩容进行了改进,通过位运算判断新下标位置,而不需要每个节点都重新计算哈希值,提高了效率。
-
性能影响 扩容是一种代价较高的操作,需要分配新内存并重新计算所有键值对的位置,因此应尽量避免频繁扩容。
延伸
1.为什么采用2倍扩容,而不是1.5倍或者3倍扩容?
HashMap 采用 2 倍扩容,是为了性能优化、空间利用率和实现简单性的综合平衡,避免了 1.5 倍或 3 倍扩容带来的复杂性和资源浪费问题。
(1)保持哈希分布均匀性
HashMap 扩容后需要重新计算键值对的位置。如果新数组大小是 2 的幂,则通过位运算(key.hash & (newCapacity - 1))来定位数组索引。这种位运算是非常高效的,避免了取模运算(%)的性能开销。如果选择其他扩容倍数(如 1.5 倍或 3 倍),就无法简单通过位运算完成定位,计算索引的效率会降低。
(2)节约内存碎片,防止浪费空间
1.5 倍扩容:扩容后的数组大小无法保证是 2 的幂。这样 HashMap 的存储空间利用率可能下降,影响键值对的哈希分布,增加哈希冲突。
3 倍扩容:虽然可以减少扩容的频率,但扩容时占用内存会瞬间大幅增加,浪费内存空间。尤其在数据量大的情况下,内存分配的压力会显著增加。
(3)减少扩容频率与内存占用的平衡
扩容过小(如 1.5 倍)会导致频繁扩容,而扩容过大(如 3 倍)会导致一次性占用过多内存。2 倍扩容在扩容频率和扩容成本之间取得了一个平衡:扩容后内存增长速度适中,只需重新分配内存并搬移数据,避免了频繁扩容的性能开销。
(4) 兼容性与实现简单性
Java 中 HashMap 的容量始终是 2 的幂次方。2 倍扩容后,容量仍然是 2 的幂,哈希计算和分布规则无需额外调整。如果使用 1.5 倍或 3 倍扩容,则数组长度不再是 2 的幂,导致实现变得复杂。比如,哈希计算的规则需要调整,哈希分布也可能变得不均匀。
五 Java 8中,HashMap有哪些重要的改进?
在 Java 8 中,HashMap
的实现进行了重要的优化,主要集中在性能提升和处理哈希冲突的改进。以下是关键的改进点:
1,数据结构的改进
在 JDK 1.7 及之前,HashMap 的数据结构是“数组+链表”。当发生哈希冲突时,多个键值对以链表形式存储在同一个“桶”中。 在 JDK 1.8 中,引入了红黑树优化。当链表长度超过 8 时,会自动转换为红黑树,这将时间复杂度从 O(n) 降低到 O(logN),大幅提高查找效率。
2,哈希算法的改进
在JDK 1.7时直接使用 hashCode 的低位进行哈希运算,这样当 table 长度较小时,高位没有参与计算,导致哈希分布不均。Java 8 使用了一种新的哈希函数实现(基于 MurmurHash
的思想),以减少哈希冲突的概率。这个优化使键的分布更加均匀,即使是质量较差的哈希码也能避免集中到某些桶中。
3,扩容位置改进
在 Java 7 中,扩容时需要重新计算每个元素的哈希值。 在 Java 8 中,扩容优化为利用位运算快速判断新位置:每个元素的哈希值只需要检查高位变化即可决定分配到新桶或保留在原桶中。例如,当容量从 16 扩展到 32 时,桶的数量翻倍,每个元素的位置只需要通过 (hash & (newCapacity - 1))
判断是否需要迁移。这种优化减少了扩容时的计算开销。
4,扩容触发机制改进
在JDK 1.7中扩容是“先扩容后插入”,无论是否发生哈希冲突,都会执行扩容操作,可能导致无效扩容。在JDK 1.8中扩容变为“先插入再扩容”,仅在插入后元素总量超过阈值,或某条链表因哈希冲突长度超过 8 且当前数组容量未达到 64 时,才会触发扩容,减少了不必要的操作。
延伸
1,改进的哈希算法详解
在 Java 8 中,HashMap
的哈希函数对键的哈希码做了更多处理,以减少冲突。它通过高位和低位的混合(h ^ (h >>> 16)
)来避免低质量的哈希函数导致的冲突。
示例:
static final int hash(Object key) {int h;return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}
这种设计使得高位和低位都能参与哈希桶的定位,减少了哈希冲突的概率,尤其是对于哈希值分布不均的键。
2,与 Java 7 HashMap 的对比
特性 | Java 7 | Java 8 |
---|---|---|
冲突处理 | 链表 | 链表 + 红黑树 |
时间复杂度(最坏情况) | O(n) | O(log n)(链表转红黑树后) |
哈希算法 | 哈希码简单混合 | 哈希码高位与低位的混合 |
扩容机制 | 重新计算哈希值 | 基于高位判断新桶位置 |
示例对比
Java 7 性能退化示例:
import java.util.HashMap;
public class HashMapTest {public static void main(String[] args) {HashMap<Integer, String> map = new HashMap<>();for (int i = 0; i < 1000; i++) {map.put(i * 16, "value" + i); // 强制让哈希冲突}System.out.println(map); // 性能会退化为 O(n)}
}
Java 8 的改进: 在相同情况下,Java 8 中链表会转化为红黑树,从而避免退化问题。
3,HashMap能不能无限扩容?
HashMap 的扩容最终受限于 JVM 所能提供的内存。当 HashMap 的容量增长到超过 JVM 可用的堆内存大小时,扩容操作将无法成功,可能会导致 OutOfMemoryError。适用于中小规模的数据存储,实际开发中,由于 HashMap 的扩容和 rehashing 都是相对昂贵的操作,大量的元素插入可能会导致系统性能的显著下降。
4,树化后删除元素能不能回退成链表?
当红黑树中的元素数量减少到 6 时,HashMap 会将红黑树退化回链表,红黑树的结构维护成本较高,涉及复杂的旋转和调整操作。如果元素数量较少,链表反而更加高效。
六 HashMap是否是线程安全的?
HashMap
是非线程安全的。HashMap
是 Java 中的一个常用集合类,用于存储键值对。由于它在设计时没有考虑线程安全问题,所以在多线程环境中,多个线程同时对 HashMap
进行读写操作可能导致数据不一致、死循环等问题。
延伸
1. 为什么 HashMap
不是线程安全的
HashMap
的非线程安全性主要体现在以下几个方面:
-
并发修改导致数据不一致:
-
多个线程同时对
HashMap
进行修改(如put()
、remove()
等),可能导致数据被覆盖或丢失,最终状态不可预测。 -
示例问题:线程 A 和线程 B 同时向
HashMap
中插入数据,线程 A 可能会覆盖线程 B 的修改,导致丢失线程 B 的数据。
-
-
扩容操作的线程安全问题:
-
当
HashMap
的容量达到阈值时,会触发扩容(rehash),即将元素重新分布到新的数组中。 -
如果在多线程环境中发生扩容操作,可能导致死循环或数据丢失。
-
原因:扩容过程中,
HashMap
会通过链表的遍历重新分配元素。如果多个线程同时执行扩容操作,链表的结构可能被破坏,导致循环引用。
-
-
无同步机制:
-
HashMap
的方法(如put()
、get()
等)没有任何同步措施,不会主动加锁,因此多个线程同时访问共享的HashMap
会导致线程安全问题。
-
2.如何使HashMap变得线程安全?
HashMap
本身不是线程安全的,如果在多线程环境下使用可能会出现数据不一致、死循环等问题。要使 HashMap
线程安全,可以采用以下几种方法:
-
使用
Collections.synchronizedMap
-
将HashMap包装成线程安全的同步Map。
-
示例代码:
Map<String, String> synchronizedMap = Collections.synchronizedMap(new HashMap<>());
-
这种方式会为所有操作加锁,适合简单的多线程访问,但性能较低。
2.使用 ConcurrentHashMap
-
ConcurrentHashMap
是 Java 提供的线程安全实现,采用分段锁机制(Java 8 后基于 CAS 和分段锁结合)。 -
示例代码:
Map<String, String> concurrentMap = new ConcurrentHashMap<>();
-
ConcurrentHashMap
提供更高的并发性能,是线程安全的推荐选择。
3.手动加锁
-
可以使用
synchronized
或ReentrantLock
在关键代码块上加锁。 -
示例代码:
Map<String, String> map = new HashMap<>(); synchronized (map) { map.put("key", "value"); }
-
这种方式适合特定场景,但需要自行管理锁,代码复杂且容易出错。
相关文章:
【八股战神篇】Java集合高频面试题
专栏简介 八股战神篇专栏是基于各平台共上千篇面经,上万道面试题,进行综合排序提炼出排序前百的高频面试题,并对这些高频八股进行关联分析,将每个高频面试题可能进行延伸的题目再次进行排序选出高频延伸八股题。面试官都是以点破…...
STM32F103定时器1每毫秒中断一次
定时器溢出中断,在程序设计中经常用到。在使用TIM1和TIM8溢出中断时,需要注意“TIM_TimeBaseStructure.TIM_RepetitionCounter0;”,它表示溢出一次,并可以设置中断标志位。 TIM1_Interrupt_Initializtion(1000,72); //当arr1…...
BC 范式与 4NF
接下来我们详细解释 BC 范式(Boyce-Codd范式,简称 BCNF),并通过具体例子说明其定义和应用。 一、BC范式的定义 BC范式(Boyce-Codd范式,BCNF)是数据库规范化理论中的一种范式,它比第…...
Data whale LLM universe
使用LLM API开发应用 基本概念 Prompt Prompt 最初指的是自然语言处理研究人员为下游任务设计的一种任务专属的输入模板。 Temperature 使用Temperature参数控制LLM生成结果的随机性和创造性,一般取值设置在0~1之间,当取值接近1的时候预测的随机性较…...
数据结构第七章(四)-B树和B+树
数据结构第七章(四) B树和B树一、B树1.B树2.B树的高度 二、B树的插入删除1.插入2.删除 三、B树1.B树2.B树的查找3.B树和B树的区别 总结 B树和B树 还记得我们的二叉排序树BST吗?比如就是下面这个: 结构体也就关键字和左右指针&…...
如何利用 Python 获取京东商品 SKU 信息接口详细说明
在电商领域,SKU(Stock Keeping Unit,库存进出计量的基本单元)信息是商品管理的核心数据之一。它不仅包含了商品的规格、价格、库存等关键信息,还直接影响到库存管理、价格策略和市场分析等多个方面。京东作为国内知名的…...
【机器学习】第二章模型的评估与选择
A.关键概念 2.1 经验误差和过拟合 经验误差与泛化误差:学习器在训练集上的误差为经验误差,在新样本上的误差为泛化误差 过拟合:学习器训练过度后,把训练样本自身的一些特点当作所有潜在样本具有一般性质,使得泛化性能…...
[PMIC]PMIC重要知识点总结
PMIC重要知识点总结 摘要:PMIC (Power Management Integrated Circuit) 是现代电子设备中至关重要的组件,负责电源管理,包括电压调节、电源转换、电池管理和功耗优化等。PMIC 中的数字部分主要涉及控制逻辑、状态机、寄存器配置、通信接口&am…...
LVGL- Calendar 日历控件
1 日历控件 1.1 日历背景 lv_calendar 是 LVGL(Light and Versatile Graphics Library)提供的标准 GUI 控件之一,用于显示日历视图。它支持用户查看某年某月的完整日历,还可以实现点击日期、标记日期、导航月份等操作。这个控件…...
ubuntu安装google chrome
更新系统 sudo apt update安装依赖 sudo apt install curl software-properties-common apt-transport-https ca-certificates -y导入 GPG key curl -fSsL https://dl.google.com/linux/linux_signing_key.pub | gpg --dearmor | sudo tee /usr/share/keyrings/google-chrom…...
如何开发专业小模型
在专业领域场景下,通过针对性优化大模型的词汇表、分词器和模型结构,确实可以实现参数规模的显著缩减而不损失专业能力。这种优化思路与嵌入式设备的字库剪裁有相似性,但需要结合大模型的特性进行系统性设计。以下从技术可行性、实现方法和潜…...
EXO 可以将 Mac M4 和 Mac Air 连接起来,并通过 Ollama 运行 DeepSeek 模型
EXO 可以将 Mac M4 和 Mac Air 连接起来,并通过 Ollama 运行 DeepSeek 模型。以下是具体实现方法: 1. EXO 的分布式计算能力 EXO 是一个支持 分布式 AI 计算 的开源框架,能够将多台 Mac 设备(如 M4 和 Mac Air)组合成…...
Git Worktree 使用
新入职了一家公司,发现不同项目用的使用一个 git 仓库管理。不久之后我看到这篇文章。 Git 的设计部分是为了支持实验。一旦你确定你的工作被安全地跟踪,并且存在安全的状态,以便在出现严重错误时可以恢复,你就不会害怕尝试新…...
【Linux网络】内网穿透
内网穿透 基本概念 内网穿透(Port Forwarding/NAT穿透) 是一种网络技术,主要用于解决处于 内网(局域网)中的设备无法直接被公网访问 的问题。 1. 核心原理 内网与公网的隔离:家庭、企业等局域网内的设备…...
反射机制动态解析
代码解释与注释 package com.xie.javase.reflect;import java.lang.reflect.Field; import java.lang.reflect.Modifier;public class ReflectTest01 {public static void main(String[] args) throws ClassNotFoundException {// 1. 获取java.util.HashMap类的Class对象Class…...
10 分钟打造一款超级马里奥小游戏,重拾20 年前的乐趣
我正在参加CodeBuddy「首席试玩官」内容创作大赛,本文所使用的 CodeBuddy 免费下载链接:腾讯云代码助手 CodeBuddy - AI 时代的智能编程伙伴 你好,我是悟空。 前言 小时候看到村里的大朋友家里都有一款 FC 游戏机,然后旁边还放…...
鸿蒙ArkUI体验:Hexo博客客户端开发心得
最近部门也在跟进鸿蒙平台的业务开发,自己主要是做 Android 开发,主要使用 Kotlin/Java 语言。,需要对新的开发平台和开发模式进行学习,在业余时间开了个项目练手,做了个基于 Hexo 博客内容开发的App。鸿蒙主要使用Ark…...
人工智能100问☞第25问:什么是循环神经网络(RNN)?
目录 一、通俗解释 二、专业解析 三、权威参考 循环神经网络(RNN)是一种通过“记忆”序列中历史信息来处理时序数据的神经网络,可捕捉前后数据的关联性,擅长处理语言、语音等序列化任务。 一、通俗解释 想象你在和朋友聊天,每说一句话都会根据之前的对话内容调整语气…...
【springcloud学习(dalston.sr1)】Zuul路由访问映射规则配置及使用(含源代码)(十二)
该系列项目整体介绍及源代码请参照前面写的一篇文章【springcloud学习(dalston.sr1)】项目整体介绍(含源代码)(一) springcloud学习(dalston.sr1)系统文章汇总如下: 【springcloud学习(dalston…...
STM32IIC协议基础及Cube配置
STM32IIC协议基础及Cube配置 一,IC协议简介1,核心特点2,应用场景 二,IC协议基础概念1,总线结构2,主从架构3,设备寻址4,起始和停止条件5,数据传输6,应答机制 三…...
Python异常模块和包
异常 当检测到一个错误时,Python解释器就无法继续执行了,反而出现了一些错误的提示,这就是所谓的“异常”, 也就是我们常说的BUG 例如:以r方式打开一个不存在的文件。 f open(‘python1.txt’,‘r’,encoding‘utf-8’) 当我们…...
每日算法刷题Day9 5.17:leetcode定长滑动窗口3道题,用时1h
9. 1652.拆炸弹(简单,学习) 1652. 拆炸弹 - 力扣(LeetCode) 思想 为了获得正确的密码,你需要替换掉每一个数字。所有数字会 同时 被替换。 如果 k > 0 ,将第 i 个数字用 接下来 k 个数字之和替换。如果 k < 0…...
题单:递归求和
宣布一个重要的事情,我的洛谷有个号叫 题目描述 给一个数组 a:a[0],a[1],...,a[n−1]a:a[0],a[1],...,a[n−1] 请用递归的方式出数组的所有数之和。 提示:递推方程 f(x)f(x−1)a[x]f(x)f(x−1)a[x]; 输入格式 第一行一个正整数 n (n≤100)n (n≤100)…...
手动实现 Transformer 模型
本文使用 Pytorch 库手动实现了传统 Transformer 模型中的多头自注意力机制、残差连接和层归一化、前馈层、编码器、解码器等子模块,进而实现了对 Transformer 模型的构建。 """ Title: 解析 Transformer Time: 2025/5/10 Author: Michael Jie &quo…...
【鸿蒙开发避坑】使用全局状态变量控制动画时,动画异常甚至动画方向与预期相反的原因分析以及解决方案
【鸿蒙开发避坑】使用全局状态变量控制动画,动画异常甚至动画方向相反的原因分析以及解决方案 一、问题复现1、问题描述2、问题示意图 二、原因深度解析1、查看文档2、调试3、原因总结:(1)第一次进入播放页面功能一切正常的原因&a…...
天拓四方锂电池卷绕机 PLC 物联网解决方案
近年来,锂电制造行业作为新能源领域的核心支柱产业,呈现出迅猛发展的态势,市场需求持续高涨。在此背景下,行业内对产品质量、生产效率以及成本控制等方面提出了更为严苛的要求。锂电制造流程涵盖混料、涂布、辊压、分切、制片、卷…...
RFID系统:技术解析与应用全景
一、技术架构与运行逻辑 RFID(Radio Frequency Identification)系统通过无线电波实现非接触式数据交互,其核心由三部分组成: 电子标签(Tag): 无源标签:依赖读写器电磁场供电&…...
hbuilderX 安装Prettier格式化代码
一、打开插件安装 搜索输入:Prettier 安装后,重启hbuilderX ,再按AltShiftF 没安装Prettier格式化: import {saveFlow,getTemplate } from "../../api/flowTemplate.js"; 安装Prettier格式化后: import …...
Python-92:最大乘积区间问题
问题描述 小R手上有一个长度为 n 的数组 (n > 0),数组中的元素分别来自集合 [0, 1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024]。小R想从这个数组中选取一段连续的区间,得到可能的最大乘积。 你需要帮助小R找到最大乘积的区间,并输出这…...
Compose笔记(二十三)--多点触控
这一节主要了解一下Compose中多点触控,在Jetpack Compose 中,多点触控处理需要结合Modifier和手势API来实现,一般通过组合 pointerInput、TransformableState 和 TransformModifier 来创建支持缩放、旋转和平移的组件。 一、 API 1. Pointer…...
2025.05.17淘天机考笔试真题第一题
📌 点击直达笔试专栏 👉《大厂笔试突围》 💻 春秋招笔试突围在线OJ 👉 笔试突围OJ 01. 魔法棋盘构造 问题描述 LYA 正在设计一款魔法棋盘游戏。游戏棋盘由 2 n 2 \times n...
python的漫画网站管理系统
目录 技术栈介绍具体实现截图系统设计研究方法:设计步骤设计流程核…...
系统架构设计(十):结构化编程
定义 结构化编程是一种遵循清晰逻辑结构、避免使用 goto 的编程方法。它强调使用有限的三种基本控制结构来组织程序,提高程序的可读性、可维护性和可测试性。 它是现代程序设计的基础,被广泛应用于命令式语言(如 C、Pascal、Java࿰…...
系统架构设计(七):数据流图
定义 数据流图(Data Flow Diagram, DFD)是一种用于表示信息系统数据流转及处理过程的图形工具。 它反映系统功能及数据之间的关系,是结构化分析与设计的重要工具。 主要符号 符号说明描述举例方框外部实体(源或终点)…...
BrepGen中的几何特征组装与文件保存详解 deepwiki occwl OCC包装库
有这种好东西我怎么不知道 AutodeskAILab/occwl: Lightweight Pythonic wrapper around pythonocc 组装几何特征以创建B-rep模型 保存为STEP和STL文件细说 Fast 快速 Searched across samxuxiang/BrepGen Ill explain how BrepGen assembles geometric features to create B-r…...
QT6 源(105)篇二:阅读与注释 QAction,给出源代码
(5)本源代码来自于头文件 qaction . h : #ifndef QACTION_H #define QACTION_H#include <QtGui/qtguiglobal.h> #if QT_CONFIG(shortcut) # include <QtGui/qkeysequence.h> #endif #include <QtGui/qicon.h> #include &…...
复旦微FMQL调试笔记:PS网口
引言 FPGA,全程现场可编程门阵列,是指一切通过软件手段更改、配置器件内部连接结构和逻辑单元,完成既定设计功能的数字集成电路。换个简单通俗的介绍方式,就好比一个全能的运动员,FPGA就是这么神奇的可以通过设定而实…...
SpringBoot启动流程深入分析
文章目录 背景启动流程listeners.starting先获取运行监听器获取SpringApplicationRunListener的实例监听器接口从spring.factories中加载数据,这里有本地缓存监听启动发布starting事件 prepareEnvironment准备环境获取或创建环境配置环境 createApplicationContext创…...
Linux - 2.系统命令
1.帮助命令 1.help [root@localhost /]# cp --help1.查看命令的信息和参数2.只能显示shell内部的命令信息3.help命令第一部分是概述,第二部分是参数详解,第三部分是说明和注意 # 使用语法 Usage: cp [OPTION]... [-T] SOURCE DESTor: cp [OPTION]... SOURCE... DIRECTORYor:…...
CSP 2024 提高级第一轮(CSP-S 2024)单选题解析
单选题解析 第 1 题 在 Linux 系统中,如果你想显示当前工作目录的路径,应该使用哪个命令?(A) A. pwd B. cd C. ls D. echo 解析:Linux 系统中,pwd命令可以显示当前工作目录的路径。pwd&#x…...
JavaScript运算符
在JavaScript开发中,运算符是编程的基础工具。它们用于执行各种操作,从简单的数学计算到复杂的逻辑判断。本文将深入探讨JavaScript中的各种运算符,包括算术运算符、比较运算符、布尔运算符、位运算符以及其他一些特殊运算符。 一、算术运算…...
无线信道的噪声与干扰
目录 1. 无线信道(wireless channel)与电磁波 2.1 电磁波的传输(无线信道传输) 2.2 视线(line of sight)传播与天线高度 2. 信道的数学模型 2.1 调制信道模型 2.1.1 加性噪声/加性干扰 2.1.2 乘性噪声/乘性干扰 2.1.3 随参信道/恒参信道 2.2 编码信道模型 2.3 小结 …...
计算机视觉与深度学习 | Python实现EMD-CNN-LSTM时间序列预测(完整源码、数据、公式)
EMD-CNN-LSTM 1. 环境准备2. 数据生成(示例数据)3. EMD分解4. 数据预处理5. CNN-LSTM模型定义6. 模型训练7. 预测与重构8. 性能评估核心公式说明1. 经验模态分解(EMD)2. CNN-LSTM混合模型参数调优建议扩展方向典型输出示例以下是使用Python实现EMD-CNN-LSTM时间序列预测的完…...
基于Yolov8+PyQT的老人摔倒识别系统源码
概述 随着人工智能技术的普及,计算机视觉在安防领域的应用日益广泛。幽络源本次分享的基于Yolov8PyQT的老人摔倒识别系统,正是针对独居老人安全监护的实用解决方案。该系统通过深度学习算法实时检测人体姿态,精准识别站立、摔倒中等…...
【网络入侵检测】基于Suricata源码分析运行模式(Runmode)
【作者主页】只道当时是寻常 【专栏介绍】Suricata入侵检测。专注网络、主机安全,欢迎关注与评论。 1. 概要 👋 在 Suricata 中抽象出线程、线程模块和队列三个概念:线程类似进程,可多线程并行执行操作;监听、解码、检…...
深入解析:java.sql.SQLException: No operations allowed after statement closed 报错
在 Java 应用程序开发过程中,尤其是涉及数据库交互时,开发者常常会遇到各种各样的异常。其中,java.sql.SQLException: No operations allowed after statement closed是一个较为常见且容易令人困惑的错误。本文将深入剖析这一报错,…...
ARM-Linux 完全入门
1.准备部分 1.1 虚拟机安装 准备VMware软件、ubuntu系统镜像安装过程 VMware安装 破解(自己百度破解码,多试几个网址,会有能用的)Ubuntu安装 配置联网 桥接 虚拟机Ubuntu系统必须能连接到外网,不然不能更新软件安装…...
前端二进制数据指南:从 ArrayBuffer 到高级流处理
前端开发中,二进制数据是处理文件、图像、音视频、网络通信等场景的基础。以下是核心概念和用途的通俗解释: 前端二进制数据介绍 1. 什么是前端二进制数据? 指计算机原始的 0 和 1 格式的数据(比如一张图片的底层代码ÿ…...
深入理解构造函数,析构函数
目录 1.引言 2.构造函数 1.概念 2.特性 3.析构函数 1.概念 2.特性 1.引言 如果一个类中什么都没有,叫作空类. class A {}; 那么我们这个类中真的是什么都没有吗?其实不是,如果我们类当中上面都不写.编译器会生成6个默认的成员函数。 默认成员函数:用户没有显…...
数值分析知识重构
数值分析知识重构 一 Question 请构造一下数值分析中的误差概念以及每一个具体数值方法的误差是如何估计的? 二 Question 已知 n 1 n1 n1个数据点 ( x i , y i ) , i 0 , 1 , ⋯ , n (x_i,y_i),i0,1,\cdots,n (xi,yi),i0,1,⋯,n,请使用多种方法建立数据之间…...