当前位置: 首页 > news >正文

Java集合面试总结(题目来源JavaGuide)

问题1:说说 List,Set,Map 三者的区别?

在 Java 中,ListSetMap 是最常用的集合框架(Collection Framework)接口,它们的主要区别如下:

1. List(列表)

  • 特点

    • 允许存储 重复元素
    • 保持插入顺序,即元素的存储顺序与遍历顺序一致。
    • 允许null值(可存多个)。
    • 提供索引访问,可以使用索引(get(int index))获取元素。
  • 常见实现类

    • ArrayList(基于数组,查询快,增删慢)
    • LinkedList(基于双向链表,查询慢,增删快)
    • Vector(线程安全的 ArrayList,但性能较低)
  • 使用场景

    • 需要有序存储元素,并且可能有重复值,例如存储一系列日志记录、待办事项等。

2. Set(集合)

  • 特点

    • 不允许存储重复元素
    • 无法通过索引访问元素(没有 get(int index) 方法)。
    • 默认情况下不保证元素的存储顺序TreeSet 除外)。
    • 允许最多一个 null 值HashSet 允许,TreeSet 不允许)。
  • 常见实现类

    • HashSet(基于哈希表,存取快,但无序)
    • LinkedHashSet有序的 HashSet,按插入顺序存储)
    • TreeSet(基于红黑树自动排序,不允许 null
  • 使用场景

    • 需要存储唯一的元素集合,例如存储用户ID、标签等。

3. Map(映射)

  • 特点

    • 键值对 (key-value) 形式存储数据。
    • Key 不可重复,但 Value 可以重复。
    • 允许最多一个 null 键,多值 null 值(TreeMap 不允许 null 键)。
  • 常见实现类

    • HashMap无序,基于哈希表,存取快,线程不安全)
    • LinkedHashMap有序的 HashMap,按插入顺序存储)
    • TreeMap排序的 Map,基于红黑树,按 Key 排序)
  • 使用场景

    • 需要存储键值映射,如学生学号-姓名、配置项键值对等。

总结对比

特性ListSetMap
是否允许重复元素允许不允许Key 不允许重复,Value 允许
是否保证顺序保证插入顺序HashSet 无序,LinkedHashSet 保证插入顺序,TreeSet 排序HashMap 无序,LinkedHashMap 保持插入顺序,TreeMap 按 key 排序
是否可存 null允许多个HashSet 允许一个HashMap 允许一个 null Key,多 null Value,TreeMap 不允许 null Key
访问方式通过索引 (get(int index))迭代器 (Iterator)通过 Key (get(K key))
适用场景需要有序存储并允许重复,如购物车、任务列表需要唯一元素,如用户ID需要键值映射,如用户信息

简单记忆

  • List 适合 有序、可重复 场景。
  • Set 适合 唯一、无序(或排序) 场景。
  • Map 适合 键值映射 场景。

问题2: List,Set,Map 在 Java 中分别由哪些对应的实现类?底层的数据结构?

在 Java 中,ListSetMap 各自有多个常见的实现类,它们的底层数据结构不同,适用于不同的场景。下面详细分析各自的实现类及其底层结构。


1. List(列表)

List 主要有以下几个实现类:

(1)ArrayList

  • 底层数据结构动态数组

  • 特点

    • 查询速度快(基于数组,通过索引访问,O(1))。

    • 插入和删除慢(涉及数据移动,O(n))。

    • 允许 null 元素,允许重复元素。

    • 线程不安全。

  • 适用场景

    • 读操作多,写操作少的场景,如缓存数据、搜索结果等。


(2)LinkedList

  • 底层数据结构双向链表

  • 特点

    • 查询速度慢(链表遍历,O(n))。

    • 插入、删除速度快(O(1),不涉及数据移动)。

    • 允许 null 元素,允许重复元素。

    • 线程不安全。

  • 适用场景

    • 频繁插入、删除元素,如任务队列、消息队列等。


(3)Vector

  • 底层数据结构动态数组

  • 特点

    • ArrayList 类似,但线程安全(方法加了 synchronized)。

    • 查询快,插入删除慢。

    • 允许 null 元素,允许重复元素。

  • 适用场景

    • 多线程环境下,需要线程安全List


2. Set(集合)

Set 主要有以下几个实现类:

(1)HashSet

  • 底层数据结构哈希表(基于 HashMap 实现,值存 HashMap 的 key)

  • 特点

    • 无序存储元素(元素顺序可能变化)。

    • 不允许重复元素

    • 允许 null 值(但只能有一个)。

    • 查询、插入、删除速度快(平均 O(1))。

  • 适用场景

    • 需要去重的集合,如存储唯一用户ID。


(2)LinkedHashSet

  • 底层数据结构哈希表 + 双向链表

  • 特点

    • 有序(按照插入顺序存储)。

    • 不允许重复元素

    • 查询、插入、删除速度比 HashSet 略慢(受链表影响)。

  • 适用场景

    • 既需要去重,又要保持插入顺序的场景,如LRU缓存。


(3)TreeSet

  • 底层数据结构红黑树(自平衡二叉搜索树)

  • 特点

    • 自动排序(默认按升序排序,可自定义 Comparator)。

    • 不允许重复元素

    • 不允许 null

    • 查询、插入、删除速度 O(log n)(比 HashSet 慢)。

  • 适用场景

    • 需要排序且去重的集合,如排行榜、时间排序数据。


3. Map(映射)

Map 主要有以下几个实现类:

(1)HashMap

  • 底层数据结构数组 + 单链表 + 红黑树(JDK 1.8 之后)

  • 特点

    • Key 无序存储,不允许重复,允许 null(最多一个)。

    • Value 允许重复,允许 null

    • 查询、插入、删除快(O(1),最坏 O(log n))。

    • 线程不安全。

  • 适用场景

    • 需要快速查找 key-value 数据,如缓存、配置项存储。


(2)LinkedHashMap

  • 底层数据结构哈希表 + 双向链表

  • 特点

    • 按插入顺序存储(可以用 accessOrder=true 变成 LRU 访问顺序)。

    • 查询、插入、删除速度略低于 HashMap(受链表影响)。

  • 适用场景

    • 需要按插入顺序遍历的 Map,如缓存实现。


(3)TreeMap

  • 底层数据结构红黑树

  • 特点

    • Key 自动排序(默认升序,可自定义 Comparator)。

    • Key 不允许 null(Value 允许)。

    • 查询、插入、删除 O(log n)

  • 适用场景

    • 需要按 key 排序Map,如时间戳排序的日志数据。


(4)Hashtable

  • 底层数据结构哈希表

  • 特点

    • 线程安全(方法加 synchronized)。

    • 不允许 null key 和 null value

    • 查询、插入、删除 O(1)

    • 效率较低(同步开销大)。

  • 适用场景

    • 需要线程安全Map(但通常用 ConcurrentHashMap 替代)。


(5)ConcurrentHashMap

  • 底层数据结构分段锁 + 哈希表(JDK 1.7),CAS + 哈希表 + 红黑树(JDK 1.8)

  • 特点

    • 线程安全,高效(分段锁 / CAS 机制)。

    • 不允许 null key 和 null value

    • 查询、插入、删除比 Hashtable 快(O(1))。

  • 适用场景

    • 高并发环境下的 Map,如缓存存储。


总结

类型

实现类

底层数据结构

主要特点

适用场景

List

ArrayList

动态数组

查询快,增删慢

读多写少

LinkedList

双向链表

插入/删除快,查询慢

频繁增删

Vector

动态数组

线程安全

多线程

Set

HashSet

哈希表

无序,不重复

唯一集合

LinkedHashSet

哈希表 + 双向链表

插入顺序

唯一且有序

TreeSet

红黑树

自动排序

唯一且排序

Map

HashMap

数组 + 链表 + 红黑树

无序,查询快

快速查找

LinkedHashMap

哈希表 + 双向链表

按插入顺序

LRU缓存

TreeMap

红黑树

Key 自动排序

需要排序

Hashtable

哈希表

线程安全,低效

线程安全(少用)

ConcurrentHashMap

哈希表 + CAS

高并发

并发环境

 问题3:有哪些集合是线程不安全的?怎么解决呢?

1. 线程不安全的集合

(1)ArrayList(线程不安全)

  • 底层数据结构:动态数组

  • 问题:多线程环境下,多个线程同时 add() 可能导致 数据覆盖、数组扩容时的数据丢失

  • 解决方案

    1. 使用 Vector(线程安全,但性能较低)

    2. 使用 Collections.synchronizedList(new ArrayList<>())

    3. 使用 CopyOnWriteArrayList(适用于读多写少的场景)


(2)HashMap(线程不安全)

  • 底层数据结构:数组 + 链表(JDK 1.7),数组 + 链表 + 红黑树(JDK 1.8)

  • 问题

    • JDK 1.7 多线程 put() 时可能引发死循环(rehash 过程中链表反转)。

    • JDK 1.8 仍然是线程不安全的,多线程 put() 可能会丢数据。

  • 解决方案

    1. 使用 ConcurrentHashMap(高性能并发 Map,推荐)

    2. 使用 Collections.synchronizedMap(new HashMap<>())(性能较低)

    3. 使用 Hashtable(线程安全但性能差,较少使用)


2. ArrayList vs. Vector(高频对比)

对比项

ArrayList

Vector

线程安全

非线程安全

线程安全(synchronized)

底层数据结构

动态数组

动态数组

扩容方式

1.5x 扩容

2x 扩容

性能

高(无锁)

低(同步开销大)

适用场景

单线程

多线程(但 CopyOnWriteArrayList 更推荐)

💡 为什么 Vector 不推荐?

  • Vector 的方法使用 synchronized 关键字,导致所有方法都串行执行,性能较低。

  • 多线程环境下,更推荐 CopyOnWriteArrayListCollections.synchronizedList(new ArrayList<>())


3. HashMap vs. ConcurrentHashMap(高频对比)

对比项

HashMap

ConcurrentHashMap

线程安全

非线程安全

线程安全

底层数据结构

数组 + 链表(JDK 1.7)
数组 + 链表 + 红黑树(JDK 1.8)

JDK 1.7分段锁 + 哈希表(Segment 机制)
JDK 1.8CAS + synchronized + 红黑树

null Key / Value

✅ 允许 null Key 和 null Value

不允许 null Key 和 null Value

并发性能

低(多线程可能出错)

高(JDK 1.8 采用 CAS 机制,提高并发性能)

适用场景

单线程

高并发环境


4. ConcurrentHashMap 如何保证线程安全?

🔹 JDK 1.7(Segment 分段锁)

  • ConcurrentHashMap 采用 Segment + HashEntry 结构,将整个 Map 分成多个 Segment(默认 16 个)。

  • 每个 Segment 维护自己的锁,只有访问相同 Segment 的线程才会竞争锁,大大提高并发性。

  • 缺点Segment 结构较复杂,锁的粒度仍然较大。


🔹 JDK 1.8(CAS + synchronized + 红黑树)

  • 取消了 Segment,改为 数组 + 链表 + 红黑树 结构,与 HashMap 结构类似。

  • 核心优化

    1. CAS(Compare-And-Swap)机制:插入新元素时,先尝试用 CAS 方式写入,失败再加锁。

    2. synchronized 代替 ReentrantLock:JDK 1.8 采用 Node 级别加锁,仅在 Hash 冲突时加锁,降低锁竞争。

    3. 红黑树优化:当链表长度超过 8 时,转换为红黑树,提高查询性能。

💡 为什么 ConcurrentHashMap 性能更好?

  • HashTable全表锁,每次访问都需要 synchronized,性能低。

  • ConcurrentHashMap 采用 CAS + 局部锁,大幅提升并发性能。


5. 线程安全的解决方案(汇总)

线程不安全集合

线程安全替代方案

ArrayList

CopyOnWriteArrayList / Collections.synchronizedList(new ArrayList<>())

HashSet

Collections.synchronizedSet(new HashSet<>())

HashMap

ConcurrentHashMap / Collections.synchronizedMap(new HashMap<>())

LinkedList

BlockingQueue(如 LinkedBlockingQueue


6. 总结

  1. ArrayList vs. Vector

    • ArrayList 非线程安全,性能高。

    • Vector 线程安全,但同步开销大,不推荐。

    • 推荐CopyOnWriteArrayList(读多写少)。

  2. HashMap vs. ConcurrentHashMap

    • HashMap 非线程安全,多线程环境下可能丢数据。

    • ConcurrentHashMap 采用 CAS + synchronized 保证线程安全,高并发推荐。

  3. ConcurrentHashMap 如何保证线程安全?

    • JDK 1.7Segment 分段锁(16 个小锁)。

    • JDK 1.8CAS + synchronized` + 红黑树(更高效)。

如果你在面试中被问到: 👉 ArrayList 和 Vector 的区别?

  • Vector 是同步的,ArrayList 不是,性能上 ArrayList 更好。

  • 现在不推荐 Vector,而是使用 CopyOnWriteArrayList

👉 HashMap 和 ConcurrentHashMap 的区别?

  • HashMap 非线程安全ConcurrentHashMap 线程安全,高并发推荐。

  • JDK 1.8 ConcurrentHashMap 采用 CAS + synchronized,比 JDK 1.7 更高效。

问题4: HashMap 查询,删除的时间复杂度

1. HashMap 底层数据结构(JDK 1.8 之后)

HashMap 采用 数组 + 链表 + 红黑树 作为底层数据结构:

  • 当没有哈希冲突时(即均匀分布的情况下):时间复杂度为 O(1)

  • 当发生哈希冲突时

    • 链表存储:查找或删除需要遍历链表,最坏时间复杂度 O(n)

    • 红黑树存储(链表长度 ≥ 8 时转换为红黑树):查询、删除的时间复杂度降为 O(log n)


2. HashMap 查询的时间复杂度

  • 理想情况下(无哈希冲突)

    • 通过 key 计算 hash 值,找到数组索引,直接返回值,时间复杂度 O(1)

  • 最坏情况(所有 key 哈希冲突,存储为链表)

    • 需要遍历整个链表,时间复杂度 O(n)

  • 优化后(链表转红黑树)

    • 当链表长度 >= 8 时,自动转为红黑树,查询复杂度降为 O(log n)

最终查询时间复杂度:

  • 平均情况:O(1)

  • 最坏情况(链表):O(n)

  • 最坏情况(红黑树):O(log n)

示例:

Map<Integer, String> map = new HashMap<>();
map.put(1, "A");
map.put(2, "B");
String value = map.get(1);  // O(1)(理想情况)

3. HashMap 删除的时间复杂度

  • 理想情况下(无哈希冲突)

    • remove(key) 计算 hash,直接删除,时间复杂度 O(1)

  • 最坏情况(哈希冲突,链表存储)

    • 需要遍历链表找到 key 并删除,时间复杂度 O(n)

  • 优化后(链表转红黑树)

    • 删除操作 O(log n)

最终删除时间复杂度:

  • 平均情况:O(1)

  • 最坏情况(链表):O(n)

  • 最坏情况(红黑树):O(log n)

示例:

map.remove(1);  // O(1)(理想情况)

4. 复杂度总结

操作

平均时间复杂度

最坏时间复杂度(链表)

最坏时间复杂度(红黑树)

get(key) 查询

O(1)

O(n)

O(log n)

remove(key) 删除

O(1)

O(n)

O(log n)

🔹 面试重点:

  • JDK 1.8 之前:查询、删除最坏情况 O(n)(哈希冲突形成链表)。

  • JDK 1.8 之后:链表长度 ≥ 8 时转为红黑树,优化为 O(log n)

问题5: HashMap 的底层实现

JDK1.8 之前 : 数组和链表

JDK1.8 之后 : 多了红黑树

问题6: HashMap 的长度为什么是 2 的幂次方?

问题答案
为什么 HashMap 长度是 2 的幂?为了 优化索引计算,减少哈希冲突
如何计算索引?index = hash & (table.length - 1)
为什么用 & (length - 1) 而不是 % length位运算比取模运算更快
如果 length 不是 2 的幂,会怎样?索引分布不均,哈希冲突增加,性能下降
HashMap 如何保证 length 是 2 的幂?tableSizeFor(cap) 方法,自动调整 capacity

问题7: 比较 HashSet、LinkedHashSet 和 TreeSet 三者的异同

1. 共同点(相同点)

1.1. 都实现了 Set 接口

  • 不允许存储重复元素,如果尝试添加相同元素,新的数据会被忽略。

1.2. 允许 null

  • HashSetLinkedHashSet 允许存储一个 null 值。

  • TreeSet 不允许 null(因为 TreeSet 依赖 compareTo() 进行排序,null 无法比较)。

1.3. 不是线程安全的

  • 三者都不是线程安全的,若在多线程环境下使用,需要使用 Collections.synchronizedSet()ConcurrentSkipListSet

Set<Integer> set = Collections.synchronizedSet(new HashSet<>());

1.4. 不能通过索引访问元素

  • Set 没有 get(int index) 方法,不能像 List 那样通过索引访问。


2. 不同点(区别)

对比项

HashSet

LinkedHashSet

TreeSet

底层数据结构

哈希表(HashMap

哈希表 + 双向链表

红黑树(TreeMap

元素存储顺序

无序

按照插入顺序

自动排序(默认升序,可自定义)

是否排序

不排序

不排序(但保持插入顺序)

排序(按 compareTo() 规则)

允许 null

允许 1 个 null

允许 1 个 null

不允许 null

查询性能

🚀 O(1)(哈希存储,最快)

🚀 O(1)(哈希存储)

🐌 O(log n)(红黑树,较慢)

插入性能

🚀 O(1)(哈希存储)

🚀 O(1)(哈希存储)

🐌 O(log n)(红黑树,较慢)

删除性能

🚀 O(1)

🚀 O(1)

🐌 O(log n)

适用场景

需要快速查找的集合

需要保留插入顺序的集合

需要排序的集合


3. 三者的底层实现

(1)HashSet

  • 底层使用 HashMapSet 的值存储在 HashMap 的 key 中,所有 value 设为 Object 类型的固定值

  • 元素无序存储,无法保证插入顺序。

public HashSet() {map = new HashMap<>();
}
public boolean add(E e) {return map.put(e, PRESENT) == null;
}

适用场景:需要快速去重,不关心元素顺序


(2)LinkedHashSet

  • 底层使用 LinkedHashMap,通过双向链表维护插入顺序

  • 保证遍历顺序与插入顺序一致

    public LinkedHashSet() {super(16, .75f, true); // 继承 LinkedHashMap
    }
    

适用场景去重但保持插入顺序,如 LRU 缓存。


(3)TreeSet

  • 底层使用 TreeMap,基于红黑树存储

  • compareTo() 结果自动排序,默认升序。

  • 不允许 null,因为 null 无法参与比较。

    public TreeSet() {this(new TreeMap<>());
    }
    

适用场景需要排序的集合,如排行榜、时间排序的日志


4. 示例代码

(1)HashSet

Set<String> hashSet = new HashSet<>();
hashSet.add("B");
hashSet.add("A");
hashSet.add("C");
System.out.println(hashSet); // 输出无序:[A, C, B](顺序可能不同)

(2)LinkedHashSet

Set<String> linkedHashSet = new LinkedHashSet<>();
linkedHashSet.add("B");
linkedHashSet.add("A");
linkedHashSet.add("C");
System.out.println(linkedHashSet); // 输出顺序:["B", "A", "C"]

(3)TreeSet

Set<String> treeSet = new TreeSet<>();
treeSet.add("B");
treeSet.add("A");
treeSet.add("C");
System.out.println(treeSet); // 输出顺序:["A", "B", "C"](自动排序)

5. 选择建议(如何选择?)

场景

推荐使用

需要去重,不关心顺序,查询性能最高

HashSet(最快)

需要去重,且保持插入顺序

LinkedHashSet

需要去重,且按大小排序

TreeSet


6. 重点面试问题

💡 1. HashSet、LinkedHashSet、TreeSet 的区别?

  • HashSet:基于 HashMap,无序存储,O(1) 查询

  • LinkedHashSet:基于 LinkedHashMap,有序存储

  • TreeSet:基于 TreeMap,自动排序,O(log n) 查询

💡 2. HashSet 为什么查询快?

  • HashSet 基于 HashMap,使用 hashCode() 计算索引,查询平均 O(1)

💡 3. TreeSet 为什么不允许 null

  • TreeSet 依赖 compareTo() 进行排序,而 null 不能比较。

💡 4. TreeSet 是如何排序的?

  • 通过 Comparable 接口 (compareTo()) 或 Comparator 自定义排序规则。


7. 总结

Set 类型

底层数据结构

顺序

查询性能

插入/删除性能

是否排序

HashSet

哈希表(HashMap

无序

🚀 O(1)

🚀 O(1)

LinkedHashSet

哈希表 + 双向链表(LinkedHashMap

插入顺序

🚀 O(1)

🚀 O(1)

TreeSet

红黑树(TreeMap

排序

🐌 O(log n)

🐌 O(log n)

🔹 总结

  • HashSet 最快,但无序。

  • LinkedHashSet 有序,比 HashSet 稍慢。

  • TreeSet 自动排序,但性能最慢(O(log n))。

问题8: HashMap 和 Hashtable 的区别?HashMap 和 HashSet 区别?HashMap 和 TreeMap 区别? ConcurrentHashMap 和 Hashtable 的区别?

1. HashMap vs. Hashtable(区别)

对比项

HashMap

Hashtable

线程安全

非线程安全

线程安全(方法使用 synchronized 修饰)

底层数据结构

数组 + 链表(JDK 1.7)
数组 + 链表 + 红黑树(JDK 1.8)

数组 + 链表

性能

🚀 高(无锁)

🐌 低(全表锁)

null 是否允许

允许 null key 和 null value

不允许 null key 和 null value

扩容方式

capacity * 2(翻倍扩容)

capacity * 2 + 1

适用场景

单线程或高并发(推荐使用 ConcurrentHashMap

低并发场景(通常不推荐)

总结:

  • HashMap 性能更高,适用于 单线程或并发环境(推荐 ConcurrentHashMap

  • Hashtable 所有方法加锁,线程安全但性能低,一般不推荐使用。

💡 面试问法:

  • 为什么 Hashtable 不推荐使用?

    • Hashtable 全表锁,并发效率低,通常使用 ConcurrentHashMap 替代。


2. HashMap vs. HashSet(区别)

对比项

HashMap

HashSet

实现接口

Map<K, V>

Set<E>

数据存储方式

key-value 形式

仅存 key,值始终为 new Object()

底层数据结构

数组 + 链表 + 红黑树(JDK 1.8)

基于 HashMapvalue 是固定对象

是否允许重复

key 唯一value 可重复

不允许重复元素

null 是否允许

key 允许一个 nullvalue 可多个 null

允许一个 null

查询性能

🚀 O(1)

🚀 O(1)

适用场景

需要存储键值对(如用户 ID -> 用户信息)

需要存储唯一元素集合(如用户 ID 集合)

总结:

  • HashMap 存储键值对HashSet 仅存储 key(基于 HashMap 实现)。

  • HashSet 去重能力基于 HashMapkey 唯一性

💡 面试问法:

  • HashSet 为什么是基于 HashMap 实现的?

    • HashSet 本质上就是 HashMapvalue 始终存一个固定对象。

public boolean add(E e) {return map.put(e, PRESENT) == null;
}

3. HashMap vs. TreeMap(区别)

对比项

HashMap

TreeMap

底层数据结构

数组 + 链表 + 红黑树

红黑树(TreeMap

排序方式

无序

自动排序(默认升序)

查询性能

🚀 O(1)(无冲突)

🐌 O(log n)(红黑树)

null 是否允许

key 允许 null

key 不允许 null

适用场景

需要快速查找的键值对

需要排序的键值对(如排行榜)

总结:

  • HashMap 查询快(O(1))无序,适合快速存取数据

  • TreeMap 自动排序(O(log n)),适用于需要排序的场景

💡 面试问法:

  • 如果 HashMap 需要排序怎么办?

    • 使用 TreeMap 或者 LinkedHashMap

4. ConcurrentHashMap vs. Hashtable(区别)

对比项

ConcurrentHashMap(推荐)

Hashtable(已淘汰)

底层数据结构

JDK 1.7:分段锁(Segment
JDK 1.8:CAS + synchronized(红黑树)

哈希表 + 全表锁

锁的粒度

局部锁(高并发)

全表锁(低效)

查询性能

🚀 高(读 O(1),写 O(1) ~ O(log n))

🐌 低(所有方法 synchronized

null 是否允许

不允许 null key/value

不允许 null key/value

适用场景

高并发环境(推荐)

低并发环境(已淘汰)

总结:

  • ConcurrentHashMap 替代 Hashtable,采用 CAS + 局部锁,更高效。

  • Hashtable 线程安全但性能低,一般不再使用。

💡 面试问法:

  • ConcurrentHashMap 如何保证线程安全?

    • JDK 1.7Segment 分段锁(16 个小锁,提高并发性能)。

    • JDK 1.8CAS + synchronized` + 红黑树(更高效)。


5. 总结

对比项

HashMap vs. Hashtable

HashMap vs. HashSet

HashMap vs. TreeMap

ConcurrentHashMap vs. Hashtable

线程安全

❌ HashMap 非线程安全,❌ Hashtable 线程安全(但慢)

HashMap 存 key-value,HashSet 只存 key

HashMap 无序,TreeMap 排序

ConcurrentHashMap 更高效(局部锁),Hashtable 全表锁(淘汰)

底层结构

HashMap:哈希表,Hashtable:哈希表(带锁)

HashSet 基于 HashMap

HashMap 哈希表,TreeMap 红黑树

ConcurrentHashMap 分段锁(JDK 1.7) / CAS + synchronized(JDK 1.8)

查询性能

🚀 O(1) vs. 🐌 O(1)(但有锁)

🚀 O(1) vs. 🚀 O(1)

🚀 O(1) vs. 🐌 O(log n)

🚀 O(1) vs. 🐌 O(1)(但有锁)

是否排序

❌ 都无序

❌ 都无序

❌ HashMap 无序,✅ TreeMap 排序

❌ 都无序

null 允许性

HashMap 允许 null key/value,Hashtable 不允许 null

✅ HashSet 允许一个 null

❌ TreeMap 不允许 null key

❌ ConcurrentHashMap 不允许 null

🚀 面试重点:

  • 高并发环境:ConcurrentHashMap 代替 Hashtable

  • 需要排序:用 TreeMap

  • 去重:用 HashSet(基于 HashMap

 问题9:ConcurrentHashMap 线程安全的具体实现方式/底层具体实现

1. JDK 1.7 中的实现(分段锁)

在 JDK 1.7 中,ConcurrentHashMap 采用了 分段锁(Segment Locking) 机制。HashMap 的每个**桶(Segment)**都是独立加锁的,允许多个线程并发操作不同的段,但同一段内的操作需要加锁。

1.1. 分段锁模型

  • ConcurrentHashMap 会把整个 map 划分为多个 段(Segment),每个段内部维护一个 HashMap,并且每个段有一个锁。

  • 每个段都可以并发操作,不同段之间的锁是独立的,这就避免了全表锁定,从而大大提高了并发性能。

  • 每个段的默认大小是 16(即 16 个桶),并且段数可以动态调整。

1.2. 锁粒度

  • 锁定段: 每次只能锁住某个段(而不是整个 ConcurrentHashMap)。

  • 不同段的并发访问: 不同线程可以并发地对不同段进行 getput 等操作。

  • 同一段的并发访问: 如果多个线程访问同一段的不同元素,则这些线程会被阻塞,直到持有该段锁的线程释放锁。

1.3. 分段锁的代码示例

public class ConcurrentHashMap<K, V> {static final int MAX_SEGMENT = 16; // 默认分成16个段final Segment<K, V>[] segments;// Segment 内部结构static final class Segment<K, V> extends ReentrantLock implements Serializable {transient volatile HashEntry<K, V>[] table;transient volatile int count;final float loadFactor;Segment(int initialCapacity, float loadFactor) {this.loadFactor = loadFactor;// Initialize the segment's hash table with the given capacity}// Segment 内部的操作方法(put、get 等)public V get(Object key) {// 获取 key 对应的 value}public void put(K key, V value) {// 将 key-value 对存入当前段的 table 中}}// 主 Map 操作,基于多个 Segment 来完成public V get(Object key) {int hash = key.hashCode();Segment<K, V> segment = segmentFor(hash);return segment.get(key);}public void put(K key, V value) {int hash = key.hashCode();Segment<K, V> segment = segmentFor(hash);segment.put(key, value);}private Segment<K, V> segmentFor(int hash) {return segments[(hash >>> 16) & (segments.length - 1)];}
}

1.4. 分段锁模型的优缺点

优点:

  • 细粒度锁:只锁住某一段,多个线程可以并行操作不同的段,并行度较高。

  • 线程安全:每个段是独立加锁的,避免了全表加锁带来的性能瓶颈。

缺点:

  • 内存占用高:每个段内部都是一个完整的 HashMap,在大数据量时可能会占用较多内存。

  • 锁竞争:如果多个线程访问同一段,仍然会发生阻塞。

2. JDK 1.8 中的实现(CAS + synchronized

在 JDK 1.8 中,ConcurrentHashMap 做了重大优化,去除了分段锁,改用 CAS(Compare-And-Swap)synchronized 来实现线程安全。其底层不再使用多个段,而是直接将数据存储在一个 桶数组(数组 + 链表 + 红黑树) 中,通过 分段锁和局部锁 的方式来提供高并发性。

2.1. CAS 和 synchronized 的组合

  • CASConcurrentHashMap 采用 乐观锁,在更新数据时首先通过 CAS 操作尝试更新,如果失败(例如并发更新),则进行重试。

  • synchronized:对于需要一致性的操作(如扩容),采用 synchronized 锁定局部区域(如某个桶),保证数据一致性。

2.2. JDK 1.8 的底层结构

  1. 桶数组:和 HashMap 类似,ConcurrentHashMap 内部使用数组来存储键值对。每个桶可以是 链表(哈希冲突时)或 红黑树(当链表过长时转换为红黑树)。

  2. 每个桶的操作

    • 使用 synchronized 锁定某个桶的插入、删除、查找操作。

    • 对于普通操作(如插入、查询),采用 CAS 来保证数据的一致性。

  3. 扩容:当负载因子超过一定阈值时,ConcurrentHashMap 会进行扩容(桶数翻倍),这时需要用 synchronized 来保护扩容过程。

2.3. JDK 1.8 代码示例

public class ConcurrentHashMap<K, V> {// 存储数据的桶数组transient volatile Node<K, V>[] table;private final float loadFactor = 0.75f;private transient volatile int sizeCtl;// 锁定某个桶public V get(Object key) {int hash = hash(key);Node<K, V> e;if ((e = table[hash & (table.length - 1)]) != null) {// 通过链表查找,若链表长度大于阈值转为红黑树synchronized (e) {// 查找并返回}}return null;}// 使用 CAS 更新值public boolean putIfAbsent(K key, V value) {int hash = hash(key);Node<K, V> e;if ((e = table[hash & (table.length - 1)]) != null) {// 使用 CAS 更新,如果失败则重试}return true;}// 扩容private void resize() {synchronized (this) {// 扩容并重置桶数组}}// hash 计算(保证一致性)private int hash(Object key) {return key.hashCode();}
}

2.4. JDK 1.8 实现的优缺点

优点:

  • 更高效:通过 CAS 和局部锁提高了并发性能,不需要全表加锁。

  • 扩展性强:自动扩容时,通过同步锁保护内存,避免了扩容过程中的数据不一致。

  • 支持高并发:多个线程可以在不同桶上并行操作,极大提高了吞吐量。

缺点:

  • 复杂度高:相比 JDK 1.7,JDK 1.8 的实现更加复杂,使用了 CAS 和 synchronized 等技术,需要处理各种竞争条件。

  • 内存开销:每个桶存储的是 Node,这比 HashMap 更占用内存。


3. 线程安全的关键点

  • CAS(Compare-And-Swap):乐观锁的一种实现方式,通过原子操作检查和更新数据。如果当前数据符合预期,则修改数据;否则重试。

  • synchronized:用于保护需要保证一致性的关键操作(如扩容、迁移)。

  • 红黑树优化:当链表的长度超过一定阈值(8),HashMap 会将链表转换为红黑树,优化查询性能。


4. 总结

  • JDK 1.7:使用 分段锁,将 ConcurrentHashMap 划分为多个段,每个段有一个独立的锁,多个线程可以并行操作不同的段。

  • JDK 1.8:采用 CAS + synchronized 技术,使用桶数组(数组 + 链表 + 红黑树)来存储数据。通过局部锁和 CAS 实现高并发。

  • 线程安全性ConcurrentHashMap 通过 细粒度锁(桶级别、段级别锁)和 CAS 操作 保证线程安全。

ConcurrentHashMap 是高并发场景下非常常用的工具,在需要线程安全的并发环境下,它是 HashtablesynchronizedMap 的更好替代品。

相关文章:

Java集合面试总结(题目来源JavaGuide)

问题1&#xff1a;说说 List,Set,Map 三者的区别&#xff1f; 在 Java 中&#xff0c;List、Set 和 Map 是最常用的集合框架&#xff08;Collection Framework&#xff09;接口&#xff0c;它们的主要区别如下&#xff1a; 1. List&#xff08;列表&#xff09; 特点&#xf…...

【区块链】深入理解椭圆曲线密码学(ECC)

&#x1f308;个人主页: 鑫宝Code &#x1f525;热门专栏: 闲话杂谈&#xff5c; 炫酷HTML | JavaScript基础 ​&#x1f4ab;个人格言: "如无必要&#xff0c;勿增实体" 文章目录 深入理解椭圆曲线密码学(ECC)1. 概述2. 椭圆曲线的数学基础2.1 基本定义2.2 有限…...

接口游标分页

由于数据库本身的的限制(以MySQL为例),以 page_num,page_size 为代表的偏移分页方式不可避免的会遇到深分页问题。 不过用户若要找符合条件的少量数据,通过翻页则十分低效,且大多用户也不会往后翻很多页,故对于C端筛选数据场景,限制分页数量增加筛选条件才是标准解决方…...

大数据数仓实战项目(离线数仓+实时数仓)2

目录 1.课程目标和课程内容介绍 2.数仓维度建模设计 3.数仓为什么要分层 4.数仓分层思想和作用 5.数仓中表的种类和同步策略 6.数仓中表字段介绍以及表关系梳理 订单表itcast_orders 订单明细表 itcast_order_goods 商品信息表 itcast_goods 店铺表 itcast_shops 商…...

C++输入输出(上)

cin和cout cin是C中提供的标准输入流对象,一般针对的是键盘,也就是从键盘上输入的字符流,使用 cin来进行数据的提取,cin一般是和 >> (流提取运算符) 配合使用的。 cin的功能和scanf是类似的 cout是C中提供的标准输出流对象,一般针对的是控制台的窗口,也就是将数据以字符…...

SpringBoot 连接Elasticsearch带账号密码认证 ES连接 加密连接

依赖 <dependency><groupId>org.elasticsearch.client</groupId><artifactId>elasticsearch-rest-high-level-client</artifactId> </dependency>配置文件 es:ip: 172.23.4.130port: 9200user: elasticpassword: qwertyuiop读取配置文件…...

选择排序

选择排序的基本思想&#xff1a; 每⼀次从待排序的数据元素中选出最⼩&#xff08;或最⼤&#xff09;的⼀个元素&#xff0c;存放在序列的起始位置&#xff0c;直到全部待 排序的数据元素排完。 直接选择排序 1. 在元素集合 array[i]--array[n-1] 中选择关键码最⼤(⼩)的数据…...

Linux——进程概念

目录 一、系统调用和库函数概念二、基本概念三、描述进程-PCB3.1 task_struct-PCB的一种3.2 task_ struct内容分类 四、组织进程五、查看进程六、通过系统调用获取进程标示符七、通过系统调用创建进程- fork初始7.1 fork函数创建子进程7.2 fork 之后通常要用 if 进行分流 八、进…...

强化学习笔记(5)——PPO

PPO视频课程来源 首先理解采样期望的转换 变量x在p(x)分布下&#xff0c;函数f(x)的期望 等于f(x)乘以对应出现概率p(x)的累加 经过转换后变成 x在q(x)分布下&#xff0c;f(x)*p(x)/q(x) 的期望。 起因是&#xff1a;求最大化回报的期望&#xff0c;所以对ceta求梯度 具体举例…...

Java设计模式:行为型模式→状态模式

Java 状态模式详解 1. 定义 状态模式&#xff08;State Pattern&#xff09;是一种行为型设计模式&#xff0c;它允许对象在内部状态改变时改变其行为。状态模式通过将状态需要的行为封装在不同的状态类中&#xff0c;实现对象行为的动态改变。该模式的核心思想是分离不同状态…...

postgresql的用户、数据库和表

在 PostgreSQL 中&#xff0c;用户、数据库和表是关系型数据库系统的基本组成部分。理解这些概念对数据库管理和操作至关重要。下面是对这些概念的详细解释&#xff1a; 1. 用户&#xff08;User&#xff09; 在 PostgreSQL 中&#xff0c;用户&#xff08;也称为 角色&#…...

什么是Rust?它有什么特点?为什么要学习Rust?

什么是Rust&#xff1f;它有什么特点&#xff1f;为什么要学习Rust&#xff1f; 如果你是一名编程初学者&#xff0c;或者已经有一些编程经验但对Rust感兴趣&#xff0c;那么这篇文章就是为你准备的&#xff01;我们将用简单易懂的语言&#xff0c;带你了解Rust是什么、它有什…...

Maven(Ⅱ):依赖范围,依赖传递,依赖阻断,可选依赖

1. Maven 依赖范围 概念 依赖范围&#xff08;Dependency Scope&#xff09;用于控制依赖在不同构建阶段的可见性和可用性。Maven 定义了几种不同的依赖范围&#xff0c;每种范围都有其特定的使用场景。 常见依赖范围及用途 compile&#xff1a;默认的依赖范围&#xff0c;…...

个人c项目 java项目解释

1. 测试环境与方法 中文&#xff1a; 本地测试环境&#xff1a;可以在一台配置中等的电脑上构建一个测试环境&#xff0c;利用现成的大词库数据&#xff08;例如英文词典或自定义数据集&#xff09;来构建 Trie。使用 C 语言的编译器&#xff08;例如 gcc&#xff09;编译项目&…...

51单片机看门狗系统

在 STC89C52 单片机中&#xff0c;看门狗控制寄存器的固定地址为 0xE1。此地址由芯片厂商在硬件设计时确定&#xff0c;但是它在头文件中并未给出&#xff0c;因此在使用看门狗系统时需要声明下这个特殊功能寄存器 sfr WDT_CONTR 0xE1; 本案将用一个小灯的工作状况来展示看门…...

爬虫基础(五)爬虫基本原理

目录 一、爬虫是什么 二、爬虫过程 &#xff08;1&#xff09;获取网页 &#xff08;2&#xff09;提取信息 &#xff08;3&#xff09;保存数据 三、爬虫可爬的数据 四、爬虫问题 一、爬虫是什么 互联网&#xff0c;后面有个网字&#xff0c;我们可以把它看成一张蜘蛛网…...

Android 使用ExpandableListView时,需要注意哪些细节

1. 布局属性设置 尺寸属性 宽度和高度&#xff1a;要合理设置 android:layout_width 和 android:layout_height 属性。如果设置为 match_parent&#xff0c;它会填满父容器&#xff1b;设置为 wrap_content&#xff0c;则会根据内容自动调整大小。例如&#xff0c;若想让 Exp…...

人工智能赋能企业系统架构设计:以ERP与CRM系统为例

一、引言 1.1 研究背景与意义 在数字化时代&#xff0c;信息技术飞速发展&#xff0c;人工智能&#xff08;Artificial Intelligence, AI&#xff09;作为一项具有变革性的技术&#xff0c;正深刻地影响着各个领域。近年来&#xff0c;AI 在技术上取得了显著突破&#xff0c;…...

使用HttpClient和HttpRequest发送HTTP请求

项目中经常会用到向第三方系统发送请求来传递数据或者获得信息&#xff0c;一般用的比较多的为HttpClient 和 HttpRequest&#xff0c;这里简要总结一下 HttpClient 和 HttpRequest 的用法 一、HttpClient 1. 发送get请求 public static String get(String url, Map<Stri…...

深度解析:网站快速收录与服务器性能的关系

本文转自&#xff1a;百万收录网 原文链接&#xff1a;https://www.baiwanshoulu.com/37.html 网站快速收录与服务器性能之间存在着密切的关系。服务器作为网站运行的基础设施&#xff0c;其性能直接影响到搜索引擎对网站的抓取效率和收录速度。以下是对这一关系的深度解析&am…...

Android记事本App设计开发项目实战教程2025最新版Android Studio

平时上课录了个视频&#xff0c;从新建工程到打包Apk&#xff0c;从头做到尾&#xff0c;没有遗漏任何实现细节&#xff0c;欢迎学过Android基础的同学参加&#xff0c;如果你做过其他终端软件开发&#xff0c;也可以学习&#xff0c;快速上手Android基础开发。 Android记事本课…...

DeepSeek-R1大模型学习笔记

DeepSeek-R1模型架构设计 DeepSeek-R1基于DeepSeek-V3 base模型&#xff0c;提出了一系列训练策略&#xff0c;包括基于纯强化学习的训练&#xff08;DeepSeek-R1-Zero&#xff09;、基于多阶段的训练和冷启动&#xff08;DeepSeek-R1&#xff09;、知识蒸馏等。下面的思维导图…...

Unity游戏(Assault空对地打击)开发(4) 碰撞体和刚体的添加

前言 飞机和世界的大小关系不太对&#xff0c;我稍微缩小了一下飞机。 详细步骤 选中所有地形对象&#xff0c;如果没有圈起的部分&#xff0c;点击Add Component搜索添加。 接着选中Player对象&#xff0c;添加这两个组件&#xff0c;最好&#xff08;仅对于本项目开发&#x…...

每日一题——滑动窗口的最大值

滑动窗口的最大值 题目描述示例说明 解题思路双端队列的特点实现步骤代码实现&#xff08;C语言&#xff09;代码解析 总结 题目描述 给定一个长度为 n 的数组 num 和滑动窗口的大小 size&#xff0c;找出所有滑动窗口里数值的最大值。 例如&#xff0c;如果输入数组 {2, 3, …...

DeepSeek 的含金量还在上升

大家好啊&#xff0c;我是董董灿。 最近 DeepSeek 越来越火了。 网上有很多针对 DeepSeek 的推理测评&#xff0c;除此之外&#xff0c;也有很多人从技术的角度来探讨 DeepSeek 带给行业的影响。 比如今天就看到了一篇文章&#xff0c;探讨 DeepSeek 在使用 GPU 进行模型训练…...

list容器(详解)

list的介绍及使用&#xff08;了解&#xff0c;后边细讲&#xff09; 1.1 list的介绍&#xff08;双向循环链表&#xff09; https://cplusplus.com/reference/list/list/?kwlist&#xff08;list文档介绍&#xff09; 1. list是可以在常数范围内在任意位置进行插入和删除的序…...

FinRobot:一个使用大型语言模型的金融应用开源AI代理平台

“FinRobot: An Open-Source AI Agent Platform for Financial Applications using Large Language Models” 论文地址&#xff1a;https://arxiv.org/pdf/2405.14767 Github地址&#xff1a;https://github.com/AI4Finance-Foundation/FinRobot 摘要 在金融领域与AI社区间&a…...

【llm对话系统】大模型 Llama 源码分析之 LoRA 微调

1. 引言 微调 (Fine-tuning) 是将预训练大模型 (LLM) 应用于下游任务的常用方法。然而,直接微调大模型的所有参数通常需要大量的计算资源和内存。LoRA (Low-Rank Adaptation) 是一种高效的微调方法,它通过引入少量可训练参数,固定预训练模型的权重,从而在保持性能的同时大…...

为AI聊天工具添加一个知识系统 之86 详细设计之27 数据处理:ETL

本文要点 ETL 数据提取 作为 数据项目的起点。数据的整个三部曲--里程碑式的发展进程&#xff1a; ETL : 1分形 Type()-层次Broker / 2完形 Method() - 维度Delegate /3 整形 Class() - 容器 Agent 1变象。变象 脸谱Extractor - 缠度&#xff08;物理 皮肤缠度&#xf…...

「全网最细 + 实战源码案例」设计模式——策略模式

核心思想 策略模式&#xff08;Strategy Pattern&#xff09;是一种行为型设计模式&#xff0c;用于定义一系列算法或策略&#xff0c;将它们封装成独立的类&#xff0c;并使它们可以相互替换&#xff0c;而不影响客户端的代码&#xff0c;提高代码的可维护性和扩展性。 结构 …...

框架与代码的形状

​ 作为一个代码的设计者&#xff0c;我之前讨论过代码的形状&#xff0c;从“名字”出发&#xff0c;进行讨论。代码的形状&#xff1a;重构的方向-CSDN博客 从比喻的角度来看&#xff0c;名字似代码的血和肉&#xff0c;而框架则似代码的骨架。 猎豹和大象 在大自然中&…...

解决vscode扩展插件开发webview中的请求跨域问题

在webview中是无法发送跨域请求的&#xff0c;可以通过消息机制&#xff0c;在插件中发请求&#xff0c;然后将请求结果传递给webview 我的代码是基于vscode-webview-ui-toolkit-samples-vue来写的 webview vue组件中的代码示例 async function initData() {// 向插件发送消…...

junit5定制点

一、JUnit 5 自定义定制点是什么&#xff1f; JUnit 5 提供了强大的扩展模型&#xff08;Extension Model&#xff09;&#xff0c;允许开发者通过实现特定接口&#xff08;如 BeforeEachCallback、ParameterResolver&#xff09;自定义测试行为。这些接口称为定制点&#xff…...

基于SpringBoot的信息技术知识赛系统的设计与实现(源码+SQL脚本+LW+部署讲解等)

专注于大学生项目实战开发,讲解,毕业答疑辅导&#xff0c;欢迎高校老师/同行前辈交流合作✌。 技术范围&#xff1a;SpringBoot、Vue、SSM、HLMT、小程序、Jsp、PHP、Nodejs、Python、爬虫、数据可视化、安卓app、大数据、物联网、机器学习等设计与开发。 主要内容&#xff1a;…...

【Rust自学】20.1. 最后的项目:单线程Web服务器

喜欢的话别忘了点赞、收藏加关注哦&#xff08;加关注即可阅读全文&#xff09;&#xff0c;对接下来的教程有兴趣的可以关注专栏。谢谢喵&#xff01;(&#xff65;ω&#xff65;) 20.1.1. 什么是TCP和HTTP Web 服务器涉及的两个主要协议是超文本传输​​协议(Hypertext T…...

LabVIEW涡轮诊断系统

一、项目背景与行业痛点 涡轮机械是发电厂、航空发动机、石油化工等领域的核心动力设备&#xff0c;其运行状态直接关系到生产安全与经济效益。据统计&#xff0c;涡轮故障导致的非计划停机可造成每小时数十万元的经济损失&#xff0c;且突发故障可能引发严重安全事故。传统人…...

想品客老师的第十天:类

类是一个优化js面向对象的工具 类的声明 //1、class User{}console.log(typeof User)//function//2、let Hdclass{}//其实跟1差不多class Stu{show(){}//注意这里不用加逗号&#xff0c;对象才加逗号get(){console.log(后盾人)}}let hdnew Stu()hd.get()//后盾人 类的原理 类…...

注解(Annotation)

注解&#xff08;Annotation&#xff09;在 Java 中可以用来简化类的使用&#xff0c;使得被注解的类能够被自动发现、自动创建并在需要的地方直接调用&#xff0c;而不需要手动创建实例。具体来说&#xff0c;注解是用来标识类、方法、字段等的&#xff0c;它们通常与一些框架…...

使用开源项目:pdf2docx,让PDF转换为Word

目录 1.安装python 2.安装 pdf2docx 3.使用 pdf2docx 转换 PDF 到 Word pdf2docx&#xff1a;GitCode - 全球开发者的开源社区,开源代码托管平台 环境&#xff1a;windows电脑 1.安装python Download Python | Python.org 最好下载3.8以上的版本 安装时记得选择上&#…...

编程AI深度实战:AI编程工具哪个好? Copilot vs Cursor vs Cody vs Supermaven vs Aider

Cursor自己可以看成一个IDE,而且有强大的RAG功能,这让它对你的意图感知非常厉害,可以精确补全,可以感受代码片段 Aider可以看作一个袖珍,灵活,强大的扳手,怎么用都行,可以放在脚本里调用,可以看代码,可以修改代码。相比Cursor而言,它感受的是文件级别,颗粒度有些不…...

如何安全地管理Spring Boot项目中的敏感配置信息

在开发Spring Boot应用时&#xff0c;我们经常需要处理一些敏感的配置信息&#xff0c;比如数据库密码、API密钥等。以下是一个最佳实践方案&#xff1a; 1. 创建配置文件 application.yml&#xff08;版本控制&#xff09; spring:datasource:url: ${MYSQL_URL:jdbc:mysql…...

为AI聊天工具添加一个知识系统 之77 详细设计之18 正则表达式 之5

本文要点 昨天讨论了 本项目&#xff08;AI聊天工具添加一个知识系统&#xff09;中正则表达式模板的设计中可能要考虑到的一些问题&#xff08;讨论到的内容比较随意&#xff0c;暂时无法确定 那些考虑 是否 应该是正则表达式模板设计要考虑的以及 是否完整&#xff09;。今天…...

Ubuntu下Tkinter绑定数字小键盘上的回车键(PySide6类似)

设计了一个tkinter程序&#xff0c;在Win下绑定回车键&#xff0c;直接绑定"<Return>"就可以使用主键盘和小键盘的回车键直接“提交”&#xff0c;到了ubuntu下就不行了。经过搜索&#xff0c;发现ubuntu下主键盘和数字小键盘的回车键&#xff0c;名称不一样。…...

安全实验作业

一 拓扑图 二 要求 1、R4为ISP&#xff0c;其上只能配置IP地址&#xff1b;R4与其他所有直连设备间均使用共有IP 2、R3-R5-R6-R7为MGRE环境&#xff0c;R3为中心站点&#xff1b; 3、整个OSPF环境IP基于172.16.0.0/16划分&#xff1b; 4、所有设备均可访问R4的环回&#x…...

NOTEPAD++编写abap

参考下面三个链接 Notepad ABAP代码高亮显示_notepad代码高亮颜色-CSDN博客 百度安全验证 ABAP Syntax Highlighting in Notepad Part 2 - SAP Community 最后XML文件看看你可以自己增加些新语法的高亮显示...

基于python的体育新闻数据可视化及分析

项目 &#xff1a;北京冬奥会体育新闻数据可视化及分析 摘 要 随着社会的不断进步与发展&#xff0c;新时代下的网络媒体获取的信息也更加庞大和繁杂&#xff0c;相比于传统信息来源更加难以分析和辨别&#xff0c;造成了新时代媒体从业者撰写新闻的难度。在此背景下&#xff…...

C# 精炼题18道题(类,三木运算,Switch,计算器)

1.数组元素和 2.数组元素乘积 3.数组元素平均数 4.数组中最大值 5.数组中的偶数 6.数组中的阶乘 7.数组反转 8.字符串反转 9.回文字符串 10.检查回文 11.最小最大值 12.找素数 13.字符串中的最长无重复字符串 14.字符串去重 15.数组中计算两数之和 16.数字到字符…...

vue2语法速通

首先&#xff0c;git clone下来的项目要npm install下载依赖&#xff0c;如果是vue项目&#xff0c;运行通常npm run serve或者npm run dev vue速通一下 使用vite创建项目&#xff08;较快&#xff09; npm create vite 配置文件 src/ ├── assets/ # 存放…...

LabVIEW图片识别逆向建模系统

本文介绍了一个基于LabVIEW的图片识别逆向建模系统的开发过程。系统利用LabVIEW的强大视觉处理功能&#xff0c;通过二维图片快速生成对应的三维模型&#xff0c;不仅降低了逆向建模的技术门槛&#xff0c;还大幅提升了建模效率。 ​ 项目背景 在传统的逆向建模过程中&#xf…...

idea隐藏无关文件

idea隐藏无关文件 如果你想隐藏某些特定类型的文件&#xff08;例如 .log 文件或 .tmp 文件&#xff09;&#xff0c;可以通过以下步骤设置&#xff1a; 打开设置 在菜单栏中选择 File > Settings&#xff08;Windows/Linux&#xff09;或 IntelliJ IDEA > Preference…...