likes
comments
collection
share

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

作者站长头像
站长
· 阅读数 51

概述

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

HashMap介绍

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

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

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

以上是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);
    }

运行结果:

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

  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}
    }

运行结果:

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

  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());
        });
    }

运行结果:

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

总结

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

转载自:https://juejin.cn/post/7137190784754778142
评论
请登录