new HashMap() 与 Maps.newHashMap() 、Maps.newHashMapWithExpectedSize(int)的区别

1. 前提说明

  1. 之前无疑中看见小组长使用了Maps.newHashMapWithExpectedSize(int),因此来了解一下。

2. 区别

  1. new HashMap()大家都应该很熟悉了,就不过多介绍,即key value结构,链表+红黑树…

0. 导入相关jar包

 <!-- https://mvnrepository.com/artifact/com.google.guava/guava -->
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>30.1.1-jre</version>
        </dependency>

1. Maps.newHashMap()

  1. 当我们点进 其源码,发现也就是new HashMap() 跟 普通new HashMap()没区别。
  2. 可能只是为了美观吧(这个不是重点)
    在这里插入图片描述

2. Maps.newHashMapWithExpectedSize(int)

  1. Maps.newHashMapWithExpectedSize(int):创建hashMap的时候事先设置其期望的大小。

  2. 这个时候就会有人问:new HashMap(int initialCapacity) 也有实现设置大小值,有什么区别?

  3. 从源码来看清楚:

        public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
        		// 确实底层还是使用了 new HashMap(int initialCapacity) 设置大小值
        		// 但是 先对 initialCapacity 做了处理
            return new HashMap(capacity(expectedSize));
        }
    
    	static int capacity(int expectedSize) {
    		// 期望值小于3 则 就期望值+1 返回
            if (expectedSize < 3) {
                CollectPreconditions.checkNonnegative(expectedSize, "expectedSize");
                return expectedSize + 1;
            } else {
            	// 若期望值不小于3,则 先扩大1/4倍,为什么要扩大,请看后文
                return expectedSize < 1073741824 ? (int)((float)expectedSize / 0.75F + 1.0F) : 2147483647;
            }
        }
    
  4. 为什么要先将期望值扩大呢?

    1. HashMap本身是会扩容的,扩容是先将原来的数组大小*2 再将原来数组上的值迁移到新的数组上,这个过程是有开销的
    2. 而hashMap本身的负载因子是0.75 若你初始化容器大小为16,则到了 16*0.75 = 12 的时候会进行扩容。
    3. 而在你本身初始化的时候,是大概率知道这个Map的容器有多大,应该装多少,因此才去设置了初始值16。
    4. 而又因为HashMap有提前阈值(即容器达到12的时候)就扩容的,因此设置初始值就可以有点变化。
    5. 比如容器感觉只会用到10,你就初始化new HashMap(14) 即 14 = 10/0.75 + 1 (加1 是为了向上取整)
    6. 那么这个HashMap到达 14*0.75 = 10.5 的时候才会扩容,即你容器存到10个时候,都不会扩容
    7. 典型的用空间 减少其他开销。
  5. 代码测试:

    public class demoMap {
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            Map<Object, Object> map1 = new HashMap<>(10000000);
            for (int i = 0; i < 8000000; i++) {
                map1.put(i,i);
            }
            System.out.println("hashMap end: " + (System.currentTimeMillis() - start));
    
            start = System.currentTimeMillis();
            Map<Object, Object> map2 = Maps.newHashMapWithExpectedSize(10000000);
            for (int i = 0; i < 8000000; i++) {
                map2.put(i,i);
            }
            System.out.println("newHashMapWithExpectedSize end: " + (System.currentTimeMillis() - start));
        }
    }
    
    hashMap end: 12590
    newHashMapWithExpectedSize end: 3356
    

3. Maps中其他方法

1. Maps.filterKeys 过滤key 得到全新Map(Maps.filterEntries(),Maps.filterKeys()同理)

  1. 我们知道对于Map来说,想根据key来过滤一些值,代码写起来很繁琐,不想List一样有stream流写法。

  2. 因此 Maps.filterKeys 出现的挺好的,简化很多代码书写:

    public class demoMap {
        public static void main(String[] args) {
            Map<Integer,String> map = new HashMap<>();
            map.put(1,"1");
            map.put(2,"1");
            map.put(3,"1");
            map.put(4,"1");
            map.put(5,"1");
            map.put(6,"1");
            final Map<Integer, String> map1 = Maps.filterKeys(map, key -> Objects.equals(key, 5));
            final Map<Integer, String> map2 = Maps.filterKeys(map, key -> key > 2);
            System.out.println(map1);
            System.out.println(map2);
        }
    }
    
    

    在这里插入图片描述

2. Maps.difference(map,map) 比较两个map的内容

public class demoMap {
    public static void main(String[] args) {
        Map<Integer, String> map1 = new HashMap<>();
        map1.put(1, "1");
        map1.put(2, "1");
        map1.put(3, "1");
        map1.put(7, "1");

        Map<Integer, String> map2 = new HashMap<>();
        map2.put(1, "1");
        map2.put(2, "1");
        map2.put(3, "1");
        map2.put(4, "1");
        map2.put(5, "1");
        map2.put(6, "1");

        final MapDifference<Integer, String> difference = Maps.difference(map1, map2);
        // 两个map是否相同
        System.out.println(difference.areEqual());
        // 两个map共同部分
        System.out.println(difference.entriesInCommon());
        // 第一次参数中特有的值
        System.out.println(difference.entriesOnlyOnLeft());
        // 第二个参数中特有的值
        System.out.println(difference.entriesOnlyOnRight());
    }
}

在这里插入图片描述

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值