Java详解(1):HashMap介绍,HashMap的迭代,HashMap的线程安全问题

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源码分析


参考资料:

猜你喜欢

转载自blog.csdn.net/zhangpeterx/article/details/88809101