- hashmap的线程安全问题
Hashtable ht=new Hashtable();
hashmap.put("1","sss");
ht.put("2","sss");
- java.util.concurrent---JUC并发包
-
ConcurrentHashMap
JDK1.7
JDK1.8
- hashmap相关问题
存储键值对,基于哈希表的 Map 接口实现
数组+链表+红黑树(方便查找--链表,哈希冲突--数组>64,链表>8:红黑树) 负载因子0.75
当然,可以模拟一下面试场景。假设面试官问到你对 `HashMap` 的了解,你可以这样回答:
---
**面试官**:请你谈谈你对 `HashMap` 的了解,包括它的基本结构、工作原理以及优缺点。
**你**:当然。`HashMap` 是 Java 集合框架中的一个重要实现,属于 `java.util` 包中的类。它是一个基于哈希表的 `Map` 实现,用于存储键值对(key-value pairs)。
### 1. **基本结构和工作原理**
- **数据结构**:`HashMap` 内部使用数组和链表(或树)来存储数据。它的核心数据结构是一个数组,每个数组位置称为一个桶(bucket)。每个桶可以存储一个链表或树形结构,具体取决于哈希冲突的数量。
- **哈希函数**:`HashMap` 使用键的哈希值来决定存储位置。当插入一个键值对时,`HashMap` 会使用键的 `hashCode()` 方法计算哈希值,然后将其映射到数组中的一个桶位置。
- **哈希冲突**:当多个键的哈希值映射到同一个桶时,就会发生哈希冲突。`HashMap` 使用链表来解决冲突,所有哈希值相同的键值对都会存储在同一个桶中。如果桶中的元素过多,`HashMap` 会将链表转换为红黑树(从 Java 8 开始),以提高查找效率。
- **负载因子和扩容**:`HashMap` 有一个负载因子(默认是 0.75),它表示桶数组的填满程度。当实际的填充度超过负载因子时,`HashMap` 会进行扩容。扩容时,它会创建一个新的、更大的数组,并重新计算所有现有键值对的位置,这个过程称为再哈希(rehashing)。
### 2. **优点**
- **快速查找**:由于使用哈希表,`HashMap` 提供了常数时间复杂度的 `get` 和 `put` 操作(O(1)),尽管在最坏情况下(例如哈希冲突严重时)复杂度可能退化为 O(n)。
- **允许 null 值**:`HashMap` 允许一个 `null` 键和多个 `null` 值。这在某些应用场景中可能非常有用。
### 3. **缺点**
- **不保证顺序**:`HashMap` 不保证键值对的顺序,这意味着插入的顺序与迭代的顺序可能不同。如果需要有序的键值对,可以使用 `LinkedHashMap`。
- **线程不安全**:`HashMap` 是非线程安全的。在多线程环境下,如果多个线程并发修改 `HashMap`,可能会导致数据不一致或其他并发问题。在这种情况下,可以使用 `ConcurrentHashMap` 或 `Collections.synchronizedMap` 来确保线程安全。
- **内存占用**:由于使用了哈希表和链表,`HashMap` 的内存占用可能较大,尤其是当桶的数量较多时。
// 遍历元素
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + ": " + entry.getValue());
}
- ReentrantLock默认非公平锁
- copyOnwriteArrayList写时复制 读多写少
- Atomic
atomicInteger num
num.incrementAndGet() 自旋+CAS,可以控制并发
- CountDownLatch
- CyclicBarrier
- Semaphor:多个共享资源互斥的使用