hashmap

参考:

面试总结hashmap

HashMap常问面试题整理

集合初始容量(DEFAULT_CAPACITY)加载因子(DEFAULT_LOAD_FACTOR)扩容增量
ArrayList101:即当 元素个数 超过 [容量长度] 时,进行扩容原容量的 0.5倍+1 ,如 ArrayList 的容量为10,一次扩容后是容量为16
HashMap16,是2^4 或 1 << 4,可以提高查询效率0.75:即当 元素个数 超过 [容量长度的0.75倍] 时,进行扩容原容量的 1 倍 , 容量为16,一次扩容后是容量为32

hashmap的源码

public class HashMap<K,V>
    extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable
{

    //桶(capacity)容量,即数组长度.
  //即在不提供有参构造的时候,声明的hashmap的桶容量;
    static final int DEFAULT_INITIAL_CAPACITY = 4;		//初始化容量

    //极限容量,表示hashmap能承受的最大桶容量为2的30次方,
	//超过这个容量将不再扩容,让hash碰撞起来吧
    static final int MAXIMUM_CAPACITY = 1 << 30;		//最大容量

    //加载因子(loadfactor,默认0.75),负载因子有个奇特的效果,表示当当前容量大于(size/)时,
	//将进行hashmap的扩容,扩容一般为扩容为原来的两倍。
    static final float DEFAULT_LOAD_FACTOR = 0.75f;

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

    //核心的数据结构,即所谓的数组+链表的部分。
	//table 就是数组,而数组中的每个元素,都是链表的第一个结点。
    transient HashMapEntry<K,V>[] table = (HashMapEntry<K,V>[]) EMPTY_TABLE;

    //当前 HashMap 中已经存储着的键值对数量,即 HashMap.size()
    transient int size;				//已使用的容量

    //阈值算法为capacity*loadfactory,大致当map中entry数量大于此阈值时进行扩容(1.8)
	//扩容阀值。即 扩容阀值 = HashMap 总容量 * 加载因子。
	//当前 HashMap 的容量大于或等于扩容阀值的时候就会去执行扩容。
	//扩容的容量为当前 HashMap 总容量的两倍。
	//比如,当前 HashMap 的总容量为 16 ,那么扩容之后为 32 。
    int threshold;			//超过当前的多少个进行扩容

    //加载因子。所谓的加载因子就是 HashMap (当前的容量/总容量) 到达一定值的时候,
	//HashMap 会实施扩容。加载因子也可以通过构造方法中指定,默认的值是 0.75 。
	//举个例子,假设有一个 HashMap 的初始容量为 16 ,那么扩容的阀值就是 0.75 * 16 = 12 。
	//也就是说,在你打算存入第 13 个值的时候,HashMap 会先执行扩容。
    final float loadFactor = DEFAULT_LOAD_FACTOR;		//超过当前多少百分比进行扩容

    //................

	public HashMap(int initialCapacity, float loadFactor) {}

	public HashMap(int initialCapacity) {
		this(initialCapacity, DEFAULT_LOAD_FACTOR);
	}

	public HashMap() {
		this(DEFAULT_INITIAL_CAPACITY, DEFAULT_LOAD_FACTOR);
	}
	
}	

hashmap的遍历:

public static void main(String[] args) {
	Map<String, String> map = new HashMap<String, String>();
	map.put("1", "value1");
	map.put("2", "value2");
	map.put("3", "value3");

	//第一种:普遍使用,二次取值
	System.out.println("通过Map.keySet遍历key和value:");
	for (String key : map.keySet()) {
		System.out.println("key= " + key + " and value= " + map.get(key));
	}

	//第二种
	System.out.println("通过Map.entrySet使用iterator遍历key和value:");
	Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
	while (it.hasNext()) {
		Map.Entry<String, String> entry = it.next();
		System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
	}

	//第三种:推荐,尤其是容量大时
	System.out.println("通过Map.entrySet遍历key和value");
	for (Map.Entry<String, String> entry : map.entrySet()) {
		System.out.println("key= " + entry.getKey() + " and value= " + entry.getValue());
	}

	//第四种
	System.out.println("通过Map.values()遍历所有的value,但不能遍历key");
	for (String v : map.values()) {
		System.out.println("value= " + v);
	}
}

由于Map中存放的元素均为键值对,故每一个键值对必然存在一个映射关系。
Map中采用Entry内部类来表示一个映射项,映射项包含Key和Value
Map.Entry里面包含getKey()和getValue()方法

在Map集合中

values():

方法是获取集合中的所有的值----没有键,没有对应关系,

KeySet():

将Map中所有的键存入到set集合中。因为set具备迭代器。
所有可以迭代方式取出所有的键,再根据get方法获取每一个键对应的值。
keySet():迭代后只能通过get()取key.

entrySet()
Set<Map.Entry<K,V>> entrySet() //返回此映射中包含的映射关系的 Set 视图。 Map.Entry表示映射关系。
entrySet():迭代后可以e.getKey(),e.getValue()取key和value。返回的是Entry接口 。

keySet方式遍历Map的性能不如entrySet性能

因为keyset取得key所对应的value时,此时还要访问Map的map.get(key)这个方法,多遍历了一次table

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值