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

new HashMap() 与 Maps.newHashMap() 、Maps.newHashMapWithExpectedSize(int)的区别,第1张

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

文章目录

1. 前提说明2. 区别

0. 导入相关jar包1. Maps.newHashMap()2. Maps.newHashMapWithExpectedSize(int) 3. Maps中其他方法

1. Maps.filterKeys 过滤key 得到全新Map(Maps.filterEntries(),Maps.filterKeys()同理)2. Maps.difference(map,map) 比较两个map的内容

1. 前提说明
    之前无疑中看见小组长使用了Maps.newHashMapWithExpectedSize(int),因此来了解一下。
2. 区别
    new HashMap()大家都应该很熟悉了,就不过多介绍,即key value结构,链表+红黑树…
0. 导入相关jar包
 
        
            com.google.guava
            guava
            30.1.1-jre
        
1. Maps.newHashMap()
    当我们点进 其源码,发现也就是new HashMap() 跟 普通new HashMap()没区别。可能只是为了美观吧(这个不是重点)
2. Maps.newHashMapWithExpectedSize(int)

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

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

    从源码来看清楚:

        public static  HashMap 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;
            }
        }
    

    为什么要先将期望值扩大呢?

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

    代码测试:

    public class demoMap {
        public static void main(String[] args) {
            long start = System.currentTimeMillis();
            Map 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 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()同理)

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

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

    public class demoMap {
        public static void main(String[] args) {
            Map 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 map1 = Maps.filterKeys(map, key -> Objects.equals(key, 5));
            final Map 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 map1 = new HashMap<>();
        map1.put(1, "1");
        map1.put(2, "1");
        map1.put(3, "1");
        map1.put(7, "1");

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

欢迎分享,转载请注明来源:内存溢出

原文地址: http://www.outofmemory.cn/zaji/5707721.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存