1.HashMap集合简介
-
HashMap 基于哈希表的 Map 接口实现,是以 key-value 存储形式存在,即主要用来存放键值对。HashMap 的实现不是同步的,这意味着它不是线程安全的。它的 key、value 都可以为 null,此外,HashMap 中的映射不是有序的。
-
jdk1.8 之前 HashMap 由 数组 + 链表 组成,数组是 HashMap 的主体,链表则是主要为了解决哈希冲突(两个对象调用的 hashCode 方法计算的哈希值经哈希函数算出来的地址被别的元素占用)而存在的(“拉链法”解决冲突)。jdk1.8 以后在解决哈希冲突时有了较大的变化,当链表长度大于阈值(或者红黑树的边界值,默认为 8 )并且当前数组的长度大于 64 时,此时此索引位置上的所有数据改为使用红黑树存储。
补充:将链表转换成红黑树前会判断,即便阈值大于 8,但是数组长度小于 64,此时并不会将链表变为红黑树,而是选择逬行数组扩容。
这样做的目的是因为数组比较小,尽量避开红黑树结构,这种情况下变为红黑树结构,反而会降低效率,因为红黑树需要逬行左旋,右旋,变色这些操作来保持平衡。同时数组长度小于64时,搜索时间相对要快些。所以结上所述为了提高性能和减少搜索时间,底层阈值大于8并且数组长度大于64时,链表才转换为红黑树,具体可以参考 treeifyBin() 方法。
当然虽然增了红黑树作为底层数据结构,结构变得复杂了,但是阈值大于 8 并且数组长度大于 64 时,链表转换为红黑树时,效率也变的更高效。
2.HashMap的特点
- 底层是链表+数组,JDK8以后右加了红黑树
- 存储的是key-value类型的数据
- key值不允许重复,key重复会被覆盖,value运行重复
- 数据存储无序:无序指的是插入顺序和取出顺序是不—致的
- key和value都允许为空,但是只能有一个空的key
3.HashMap的常用方法
①.put(K key, V value) 将键(key)/值(value)映射存放到Map集合中
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);//向HashMap中添加元素
map.put("Tom1", 700);//向HashMap中添加元素
map.put("Tom", 100);//向HashMap中添加元素
System.out.println(map);
}
}
②.get(Object key) 返回指定键所映射的值,没有该key对应的值则返回 null,即获取key对应的value。
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);
map.put("Tom", 0);
int score = map.get("Tom");// 获取key对应的value
System.out.println(score);// key不允许重复,若重复,则覆盖已有key的value
}
}
可知,之前加入的value已被覆盖,前面的观点得证
③. size() 返回Map集合中数据数量,准确说是返回key-value的组数。
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);
map.put("Jim", 90);
map.put("Sam", 91);
System.out.println(map);
System.out.println(map.size());
}
}
④:clear() 清空Map集合
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);
map.put("Jim", 90);
map.put("Sam", 91);
map.clear();// 清空map中的key-value
System.out.println(map.size());
}
}
⑤:isEmpty () 判断Map集合中是否有数据,如果没有则返回true,否则返回false
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);
map.put("Jim", 90);
map.put("Sam", 91);
System.out.println(map.isEmpty());
map.clear();// 清空map中的key-value
System.out.println(map.isEmpty());
}
}
⑥:remove(Object key) 删除Map集合中键为key的数据并返回其所对应value值。
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map = new HashMap<String, Integer>();
map.put("Tom", 100);
map.put("Jim", 90);
map.put("Sam", 91);
map.remove("Tom");
System.out.println(map);
}
}
⑦:containsKey(Object key) Hashmap判断是否含有key
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map=new HashMap<>();
/*boolean*///判断map中是否存在这个key
System.out.println(map.containsKey("DEMO"));//false
map.put("DEMO", 1);
System.out.println(map.containsKey("DEMO"));//true
}
}
⑧:containsValue(Object value) Hashmap判断是否含有value:
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map=new HashMap<>();
/*boolean*///判断map中是否存在这个value
System.out.println(map.containsValue(1));//false
map.put("DEMO", 1);
System.out.println(map.containsValue(1));//true
}
}
⑨:Hashmap添加另一个同一类型的map下的所有数据
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map=new HashMap<>();
HashMap<String, Integer> map1=new HashMap<>();
/*void*///将同一类型的map添加到另一个map中
map1.put("DEMO1", 1);
map.put("DEMO2", 2);
System.out.println(map);//{DEMO2=2}
map.putAll(map1);
System.out.println(map);//{DEMO1=1, DEMO2=2}
}
}
⑩:Hashmap替换这个key的value
public class Test {
public static void main(String[] args) {
HashMap<String, Integer> map=new HashMap<>();
/*value*///判断map中是否存在这个key
map.put("DEMO1", 1);
map.put("DEMO2", 2);
System.out.println(map);//{DEMO1=1, DEMO2=2}
System.out.println(map.replace("DEMO2", 1));//2
System.out.println(map);//{DEMO1=1, DEMO2=1}
}
}