最近学习的Map
(1) HashMap的entry方法:
有4个参数:key,value,hash,next
key:键
value:键对应的值
hash:取址
next:发生hash碰撞时,来指向位置(比如编号为8的位置上已经有一个key为120,这时候有个key为40通过计算也在编号8的位置上,就发生了碰撞,这时8的位置指向120,120的entry里的next指向40)
(2) 遍历方法
1.keyset(一般不使用)
Map<String,String> map = new HashMap<String, String>();
map.put("aa", "123");
for (String key:map.keySet()){
System.out.println(key+"------"+map.get(key));
}
2.values(只能获取value)
Map<String,String> map = new HashMap<String, String>();
map.put("aa", "123");
for (String value : map.values()){
System.out.println(value);
}
3.entrySet(推荐使用)
Map<String,String> map = new HashMap<String, String>();
map.put("aa", "123");
for ( Map.Entry<String,String> entry : map.entrySet()){
System.out.println(entry.getKey()+"---"+entry.getValue());
}
//Map.Entry使Map的一个接口,可以使用getKey和getValue
//map.entrySet是返回一个键值映射的集合
//public abstract java.util.Set<Map.Entry<K, V>> entrySet()
4.Iterator
Map<String,String> map = new HashMap<String, String>();
map.put("aa", "123");
map.put("bb","456");
Iterator<Map.Entry<String,String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()){
Map.Entry<String,String> entry = iterator.next();
System.out.println(entry.getKey()+"----"+entry.getValue());
}
//迭代器是遍历集合的,所以要用map.entryset方法转成集合
5.map.forEach
Map<String,String> map = new HashMap<String, String>(16, 0.7F);
map.put("aa", "123");
map.put("bb","456");
map.forEach((key,value)->{
// System.out.println(key+"=="+value);
});
//该方法是lamda表达式,遍历的速度比entrySet慢大约10倍。我自己测了写简单的数据,10万条,entrySet大约7毫秒,map.forEach大约70毫秒
(3)HashMap底层原理
1.Map空的构造方法,负载因子0.75,长度是16 例子:HashMap<String, String>(16, (float) 0.75);
2.使用put方法是,存入的entry的位置的计算方法是:先把key通过hashCode()方法转换成hash码,然后对hash码进行优化,得到最后的hash码和Map的长度进行位运算(取余)(indexFor(int h, int length)),然后获得存储位置。如果Map扩容则会重新取址。
3.HashMap的最大容量:1 << 30 = 1073741824
贴出源码: MAXIMUM_CAPACITY为最大容量
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;
this.threshold = tableSizeFor(initialCapacity);
}
(4) map的常用方法
1.put
2.putIfAbsent:判断是否存在,如果存在返回旧的value,不存在返回null
3.replace:替换
4.remove:移除某个entry
5.clear:清空map
6.containsKey和containsValue:判断是否存在某个key或value
7.isEmpty:判断是否为空
8.map.forEach((key,value)->{ }) :遍历,lamda写法
9.map.getOrDefault(key , defaultValue): 判断是否存在某个key,defaultValue是如果存在输出对应的value,不存在输出默认值(defaultValue)。根据业务选择使用get还是getOrDefault。
(5)使用map的注意事项
1.一定要指定泛型。
2.使用的时候,最好指定Map的长度,减少扩容的次数。