在java中,如果数据仅由单线程访问且不需要特殊的安全保障,选择 hashmap;如果数据会被多个线程同时读写,必须选择 concurrenthashmap 以避免并发修改异常或数据不一致。具体做法是:在单线程场景下直接使用 new hashmap() 以获得最佳性能;在多线程场景下使用 new concurrenthashmap() 并利用其原子操作(如 putifabsent)来简化逻辑。

单线程环境下如何高效存储键值对
在单线程环境中,HashMap 是首选,因为它没有同步开销,访问速度最快。开发者只需实例化对象并调用标准方法即可。需要注意的是,HashMap 允许 null 键和值,且在迭代期间若结构被修改会抛出 ConcurrentModificationException。

import java.util.HashMap;
import java.util.Map;
public class SingleThreadDemo {
public static void main(String[] args) {
Map<string integer> map = new HashMap();
map.put("key1", 100);
map.put("key2", 200);
System.out.println(map.get("key1")); // 输出: 100
}
}</string>
预期结果:
控制台打印出数字 100。
程序正常结束,无异常抛出。
多线程环境下如何安全地共享Map
在多线程环境中,ConcurrentHashMap 提供了线程安全的视图,通过分段锁(JDK 1.8+ 为 CAS + synchronized)实现高并发。它不允许 null 键或值。对于复合操作(如检查存在性然后插入),应使用原子方法如 putIfAbsent 而不是先 get 再 put,后者在并发下不安全。

import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultiThreadDemo {
public static void main(String[] args) {
ConcurrentHashMap<string integer> map = new ConcurrentHashMap();
ExecutorService executor = Executors.newFixedThreadPool(5);
for (int i = 0; i {
map.putIfAbsent("task-" + id, id);
});
}
executor.shutdown();
}
}</string>
预期结果:
所有线程成功执行,不会抛出 NullPointerException 或 ConcurrentModificationException。
最终 Map 中包含 10 个键值对,键为 task-0 到 task-9。
ConcurrentHashMap 遇到 null 值时会发生什么
当向 ConcurrentHashMap 插入 null 值时,它会直接抛出 NullPointerException。这与 HashMap 不同,HashMap 允许 null 值。这一行为在多线程环境下尤为重要,因为 ConcurrentHashMap 的设计初衷是避免在读取时阻塞,而允许 null 会导致读取线程无法区分“键不存在”和“键对应值为 null”,从而破坏并发安全性。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











