Java详解(1):HashMap介绍,HashMap的迭代,HashMap的线程安全问题
本系列是Java详解,专栏地址:Java详解
HashMap介绍
HashMap是Java基于哈希表实现的Map接口。Map的意思是key-value的集合。
有几个注意事项:
- HashMap不能包含重复键
- HashMap允许null值和null键
- HashMap是一个无序集合,它不保证元素的顺序
- HashMap不是线程安全的
HashMap的使用示例如下:
import java.util.HashMap;
import java.util.Map;
public class hello {
public static void main(String[] args) {
// Creating a HashMap
Map<String, Integer> numberMapping = new HashMap<>();
// Adding key-value pairs to a HashMap
numberMapping.put("One", 1);
numberMapping.put("Two", 2);
numberMapping.put("Three", 3);
// Add a new key-value pair only if the key does not exist in the HashMap, or is mapped to `null`
numberMapping.putIfAbsent("Four", 4);
System.out.println(numberMapping);
}
}
输出结果应该如下:
{One=1, Four=4, Two=2, Three=3}
HashMap常用的方法有:
- 检查HashMap是否为空| isEmpty()
- 检查HashMap的大小| size()
- 检查HashMap中是否存在给定的键| containsKey()
- 检查HashMap中是否存在给定值| containsValue()
- 在HashMap中获取与给定键关联的值 |get()
- 在HashMap中修改与给定键关联的值| put()
- 从HashMap中删除一个键 |remove(Object key)
- 仅当HashMap与给定值相关联时才从HashMap中删除密钥| remove(Object key, Object value)
- Map接口提供了检索键值对,键集和值集合的方法| entrySet() keySet() values()
HashMap的迭代
想要迭代一个HashMap有以下这些方法:
- 使用forEach
- 使用lambda表达式
- 使用iterator()
- 使用keySet()
HashMap的线程安全问题
HashMap不是线程安全的,示例如下:
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class UnsafeHashMapExample {
public static void main(String[] args) throws InterruptedException {
Map<String, Integer> cricketTeamScore = new HashMap<>();
cricketTeamScore.put("Australia", 349);
cricketTeamScore.put("India", 250);
// Create an ExecutorService with a Thread Pool of size 10
ExecutorService executorService = Executors.newFixedThreadPool(10);
// Create a Runnable object that increments the value associated with a given key in the HashMap by one.
Runnable task = () -> {
incrementTeamScore(cricketTeamScore, "India");
};
// Submit the Runnable object to the executorService 100 times to test concurrent modifications
for(int i = 0; i < 100; i++) {
executorService.submit(task);
}
executorService.shutdown();
executorService.awaitTermination(60, TimeUnit.SECONDS);
System.out.println("Final Score of Team India : " + cricketTeamScore.get("India"));
}
// Increment the score of a team by one
private static void incrementTeamScore(Map<String, Integer> cricketTeamScore, String team) {
Integer score = cricketTeamScore.get(team);
cricketTeamScore.put(team, score + 1);
}
}
如果HashMap是线程安全的,那么结果应该是350,但输出的结果小于350,说明HashMap不是线程安全的。这是由于多个线程试图同时修改HashMap,一个线程所做的更改会被其他一些线程覆盖,并且输出变得不确定。
想要使用线程安全的HashMap,可以使用synchronizedMap,synchronizedMap是多线程安全的
另一个办法就是在HashMap的get和put方法前加锁,也就是synchronized 关键字
下一篇文章:Java详解(2):HashMap源码分析
参考资料: