guava之Maps常用示例及newHashMapWithExpectedSize()详解

谷歌提供了guava包里面有很多的工具类,现在来看Maps这个集合工具,对map集合操作做了些优化提升。

现提供如下使用实例。

package com.lxk.guavaTest;

import com.google.common.collect.Maps;

import java.util.Iterator;
import java.util.Map;

/**
 * guava Maps 测试实例
 * <p>
 * Created by lxk on 2016/11/14
 */
public class MapsTest {
    public static void main(String[] args) {
        testMaps();
    }

    /**
     * 测试 guava Maps
     */
    private static void testMaps() {
        Map<Integer, Integer> map0 = Maps.newHashMap();
        for (int i = 0; i < 10; i++) {
            map0.put(i, i);
        }
        System.out.println("map0:" + map0);

        Map<Integer, Integer> map1 = Maps.newHashMap(map0);
        map1.put(10, 10);
        System.out.println("map1:" + map1);

        //下面的这个写法呢是在初始化list的时候,说明容器的扩容界限值
        //使用条件:你确定你的容器会装多少个,不确定就用一般形式的
        //说明:这个容器超过3个还是会自动扩容的。不用担心容量不够用。默认是分配一个容量为16的数组,不够将扩容
        //详细见后面说明
        Map<Integer, Integer> map2 = Maps.newHashMapWithExpectedSize(3);
        map2.put(1, 1);
        map2.put(2, 2);
        map2.put(3, 3);
        System.out.println("map2:" + map2);

        //LinkedHashMap<K, V> 有序map
        //Map<Integer,Integer> map3 = Maps.newLinkedHashMap();
        Map<Integer, Integer> map3 = Maps.newLinkedHashMap(map1);
        //Map<Integer,Integer> map3 = Maps.newLinkedHashMapWithExpectedSize(11);
        map3.put(11, 11);
        System.out.println("map3:" + map3);

        outMapKeyValue(map3);
    }

    /**
     * 遍历Map的四种方法
     */
    private static void outMapKeyValue(Map<Integer, Integer> map3) {

        //1.通过Map.entrySet遍历key和value
        for (Map.Entry<Integer, Integer> integerEntry : map3.entrySet()) {
            System.out.println("key:" + integerEntry.getKey() + " value:" + integerEntry.getValue());
        }

        //2.通过Map.entrySet使用iterator遍历key和value-----不推荐,直接用上面的for each循环代替此方法
        Iterator<Map.Entry<Integer, Integer>> it = map3.entrySet().iterator();
        while (it.hasNext()) {
            Map.Entry<Integer, Integer> entry = it.next();
            System.out.println("key:" + entry.getKey() + " value:" + entry.getValue());
        }

        //3.通过Map.keySet遍历key;根据key得到value
        for (Integer integer : map3.keySet()) {
            System.out.println("key:" + integer + " value:" + map3.get(integer));
        }

        //4.通过Map.values()遍历所有的value,但不能遍历key
        for (Integer integer : map3.values()) {
            System.out.println("value:" + integer);
        }
    }


}


下面先是关于Maps.newHashMapWithExpectedSize(3)的源码简单分析

//返回一个 新的、空的hashmap实例,有足够多(expectedSize个)的节点(entries),保证添加过程不出现resize
//@return a new, empty {@code HashMap} with enough capacity to hold {@code expectedSize} entries without resizing
  public static <K, V> HashMap<K, V> newHashMapWithExpectedSize(int expectedSize) {
    return new HashMap<K, V>(capacity(expectedSize));
  }

  static int capacity(int expectedSize) {
    if (expectedSize < 3) {
      checkNonnegative(expectedSize, "expectedSize");
      return expectedSize + 1;
    }
    if (expectedSize < Ints.MAX_POWER_OF_TWO) { //MAX_POWER_OF_TWO = 1 << (Integer.SIZE - 2);
      // This is the calculation used in JDK8 to resize when a putAll
      // happens; it seems to be the most conservative(保守的) calculation we
      // can make.  0.75 is the default load factor.
      return (int) ((float) expectedSize / 0.75F + 1.0F);
    }
    return Integer.MAX_VALUE; // any large value //MAX_VALUE = 0x7fffffff;
  }

  static int checkNonnegative(int value, String name) {
    if (value < 0) {
      throw new IllegalArgumentException(name + " cannot be negative but was: " + value);
    }
    return value;
  }


//以下就是hashmap源码部分了。
    public HashMap(int initialCapacity) {
        this(initialCapacity, DEFAULT_LOAD_FACTOR);//DEFAULT_LOAD_FACTOR = 0.75f;加载因子默认是0.75f
    }

    public HashMap(int initialCapacity, float loadFactor) {
        if (initialCapacity < 0)
            throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity);
        if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
        if (loadFactor <= 0 || Float.isNaN(loadFactor))
            throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);

        this.loadFactor = loadFactor;//hash table 加载因子
        threshold = initialCapacity;//
        init();
    }
	
//threshold属性:英文翻译为:阈值。注释如下,就是hashmap resize的临界值。
    /**
     * The next size value at which to resize (capacity * load factor).
     * @serial
     */
    // If table == EMPTY_TABLE then this is the initial capacity at which the
    // table will be created when inflated.
    int threshold;


hashmap底层实现是如下的一个对象数组。

    /**
     * An empty table instance to share when the table is not inflated.
     */
    static final Entry<?,?>[] EMPTY_TABLE = {};

    /**
     * The table, resized as necessary. Length MUST Always be a power of two.
     */
    transient Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

Maps.newHashMapWithExpectedSize(3),初始化一个大小合适的map集合,避免在向集合添加元素的时候,因为大小不合适而resize,每次resize都得执行以下步骤:再次去分配空间,再次去计算所以元素的hashcode,再次根据hashcode计算数组的分配位置,然后数组拷贝。
这样就可以大大提升 在使用hashmap时候的性能。和不必要的空间浪费。
resize默认是*2来扩容的。

resize(2 * table.length);





  • 8
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值