HashMap使用详解,你可能不知道的API

简介: HashMap使用详解,你可能不知道的API

概述


HashMap作为一个使用频率非常高的key-value容器,在我们的项目中经常用到,而且,面试官也很喜欢问。这就要求我们不能只停留在使用层面,对于它底层的实现也需要弄明白。本文主要是针对jdk1.8中的HashMap使用层面的一个讲解,尤其是jdk1.8中新增了一些api,你都了解吗?


HashMap介绍


HashMap 最早出现在 JDK 1.2中,底层基于散列算法实现,它是一个key-value结构的容器。

  • 是一个key-value的映射容器,key不重复
  • jdk8中的HashMap基于数组+链表+红黑树实现
  • 不保证键值的顺序
  • 可以存入null值
  • 非线程安全,多线程环境下可能存在问题

1671185005310.jpg

以上是HashMap的类结构图:

  • 继承了AbstractMap,实现了Map接口,提供了key,value结构格式访问的方法
  • 实现了Cloneable接口,表示HashMap支持clone
  • 实现了Serializable接口,表示HashMap支持序列化


构造方法


方法 说明
HashMap() 构造一个默认负载因子为0.75的HashMap
HashMap(int initialCapacity, float loadFactor) 构造一个自定义初始容量和负载因子的HashMap
HashMap(Map<? extends K, ? extends V> m) 构造一个内容为m的HashMap

这里的负载因子和初始容量涉及到扩容机制,后面会重点提到。


关键方法


方法 说明 jdk8新增
V put(K key, V value) 添加key value,会覆盖相同key上的内容
V putIfAbsent(K key, V value) 添加key value,只有key不存在才会添加value
putAll(Map<? extends K, ? extends V> m) 将另外一个map中的元素添加进来
V remove(Object key) 根据key删除,返回删除关联的value
boolean remove(Object key, Object value) 只有key,value都匹配才会删除
void clear() 清空map内容
V get(Object key) 根据key获取value
V getOrDefault(Object key, V defaultValue) 根据key获取value,如果返回null,使用默认值
void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) 根据function自定义替换逻辑
replace(K key, V oldValue, V newValue) 根据key, oldvalue替换为newValue
V replace(K key, V value) 替换map中key中的值为value, 前提key在map中存在
V compute(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) 对 map 中指定 key 的值进行重新计算,如果计算出新的值是null, 会删除这个key
V computeIfAbsent(K key,Function<? super K, ? extends V> mappingFunction) 对map中不存在的key进行重新计算获取新的value, put到map中
V computeIfPresent(K key,BiFunction<? super K, ? super V, ? extends V> remappingFunction) 对map中存在的key进行重新计算获取新的value, put到map中,如果新的value是空的话,则删除这个key
V merge(K key, V value,BiFunction<? super V, ? super V, ? extends V> remappingFunction) 合并map中key下的value和传入的newValue,合并逻辑通过函数式变成定义,如果返回为null,则删除map中的key

Entry是HashMap中节点实现的接口,y用于遍历,它也新加了一些新的api。

方法 说明 jdk8新增
K getKey() 获取这个节点的key
V getValue() 获取这个节点的value
V setValue(V value) 设置这个节点的value
V remove(Object key) 根据key删除,返回删除关联的value
comparingByKey() 静态方法,获取key的排序比较器,如果map中key包含null, 空指针
comparingByValue() 静态方法,获取value的排序比较器,如果map中value包含null, 空指针
comparingByKey(Comparator<? super K> cmp) 静态方法,自定义key的排序比较器,如果map中key包含null, 空指针
comparingByValue(Comparator<? super V> cmp) 静态方法,自定义value的排序比较器,如果map中value包含null, 空指针

使用案例


  1. map的增删查基本操作
@Test
    public void test1() {
        Map<String, Integer> map = new HashMap();
        map.put("cxw", 1);
        map.put("yms", 2);
        // 会覆盖前面的key yms
        map.put("cxw", 5);
        System.out.println(map);  // {cxw=5, yms=2}
        // 不存在cxw 这个key,才会覆盖
        map.putIfAbsent("cxw", 8);
        map.putIfAbsent("cc", 1);
        System.out.println(map); // {cc=1, cxw=5, yms=2}
        Integer cxwInt = map.get("cxw");
        System.out.println(cxwInt);  // 5
        // 不存在key,使用默认值
        Integer defaultGet = map.getOrDefault("kk", 0);  // 0
        // 根据key删除
        map.remove("cc");
        // 根据key value删除, key, value都等值才会删除成功,所以这里删除不成功
        map.remove("cxw", 10);
        System.out.println(map);
    }

运行结果:

1671185027172.jpg

  1. compute相关操作
@Test
    public void test2() {
        Map<String, Integer> map = new HashMap();
        map.put("cxw", 1);
        map.put("yms", 2);
        map.put("kk", 2);
        // 计算
        map.compute("cxw", new BiFunction<String, Integer, Integer>() {
            @Override
            public Integer apply(String key, Integer integer) {
                return 100;
            }
        });
        System.out.println(map);  //{kk=2, cxw=100, yms=2}
        map.compute("cxw", new BiFunction<String, Integer, Integer>() {
            @Override
            public Integer apply(String key, Integer integer) {
                // 返回null,会删除cxw这个key
                return null;
            }
        });
        System.out.println(map);  //{kk=2, yms=2}
        // 只有key不存在才会进行操作, yms存在,所以保持不变
        map.computeIfAbsent("yms", new Function<String, Integer>() {
            @Override
            public Integer apply(String s) {
                return 10;
            }
        });
        System.out.println(map);  //{kk=2, yms=2}
        // 只有key存在才会进行操作, yms存在,所以发生变化
        map.computeIfPresent("yms", new BiFunction<String, Integer, Integer>() {
            @Override
            public Integer apply(String s, Integer integer) {
                return 10;
            }
        });
        System.out.println(map);  //{kk=2, yms=10}
    }

运行结果:

1671185107674.jpg

  1. 测试HashMap节点的comparing相关方法
@Test
    public void test3() {
        Map<String, Integer> map = new HashMap();
        map.put("cxw", 1);
        map.put("yms", 2);
        map.put("kk", 2);
        // 根据key排序
        List<Map.Entry<String, Integer>> entrys = map.entrySet().stream().sorted(Map.Entry.comparingByKey()).collect(
                Collectors.toList()
        );
        entrys.forEach(item -> {
            System.out.println(item.getKey());
        });
    }

运行结果:

1671185120371.jpg


总结


本文主要讲解了HashMap的重要特性以及重点API,特别是jdk8中新引入了一些方法,可能你都不知道,但的确有用。

目录
相关文章
|
4月前
|
XML 测试技术 API
常见的22个API面试题
常见的22个API面试题
181 0
常见的22个API面试题
|
11月前
|
存储 安全 Java
常用类和基础api(一)
常用类和基础api(一)
33 0
|
28天前
|
存储 API
Map常用API
Map常用API
27 2
|
28天前
|
API
Collection常用API
Collection常用API
26 1
|
1月前
|
存储 程序员 API
八股day05_API、String对象和集合
day05_API、String对象和集合
|
4月前
|
XML API 网络架构
API的类型及其区别是什么?
API的类型及其区别是什么?
220 0
|
Java API
Java序列化API的使用
Java序列化API的使用
97 0
|
算法 Java API
常用API算法介绍
常用API算法介绍
|
安全 Java 编译器
0:Base API-Java API 实战
0:Base API-Java API 实战
111 0
0:Base API-Java API 实战
|
机器学习/深度学习 消息中间件 API
数据类型与API(3)List
List (列表) 特点 • 有序 • 可以重复 • 左右两边插入弹出
数据类型与API(3)List