Map集合

发布时间 2023-11-21 21:01:21作者: 和哗

Map集合

Map集合总存放的元素是Entry类型的,该元素包含key和value。它是所有键值对集合的根类。它的子类HashMap便是今天需要掌握的重点。

HashMap集合

 创建HashMap的语法:

①HashMap  名称  = new  HashMap();
②HashMap  名称  = new  HashMap(初始化容量);

举个例子:

1 public class Test {
2     public static void main(String[] args) {
3         //通过调用无参构造方法生成HashMap对象
4         HashMap map = new HashMap();
5         //使用有参构造方法,提供初始化容量
6         HashMap map1 = new HashMap(10); 
7     }
8 }

HashMap中常见的方法。

存放元素

语法:

V put(K key, V value)  :是将元素添加到Map集合中

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建一个Map对象
 4         HashMap map = new HashMap();
 5         //添加元素,里面的key不能重复,如果重复则后者替换前者的value值
 6         map.put(1,"a");
 7         map.put(2,"b");
 8         map.put(1,3);
 9         System.out.println(map);
10     }
11 }

效果展示:

 可以看见当两个key值相同时,后者的value值会替换前者value值

移除元素

语法:

V remove(Object key)  :根据key值移除value值,并返回value值

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建一个Map对象
 4         HashMap map = new HashMap();
 5         //添加元素,里面的key不能重复,如果重复则后者替换前者的value值
 6         map.put(1,"a");
 7         map.put(2,"b");
 8         Object remove = map.remove(1);
 9         System.out.println("remove = " + remove);
10     }
11 }

效果展示:

修改元素

HashMap中有两种修改元素的方法,但是底层使用的仍是put方法

语法:

①V put(K key, V value)  :将key值相同修改value值
②V replace(K key, V value)  :将key值相同修改value值

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建一个Map对象
 4         HashMap map = new HashMap();
 5         //添加元素,里面的key不能重复,如果重复则后者替换前者的value值
 6         map.put(1,"a");
 7         map.put(2,"b");
 8         //使用put方法,将相同的key值中的value值进行修改
 9         map.put(1,"你好啊,我要将1中的value值替换了");
10         //使用replace方法,将相同的key值中的value值进行修改
11         map.replace(2,"你好啊,我要将2中的value值替换了");
12         System.out.println(map);
13     }
14 }

效果展示:

 可以看出两者方法实现的结果都是一样的。(一般建议使用put方法这样可以少记一个方法)。

查询元素

语法:

①V get(Object key)  :根据key获取对应的value值
②V getOrDefault(Object key, V defaultValue)  :如果指定的key存在,则获取对应的value值,否则获取defaultValue值
③Set<K> keySet()  :获取所有的key
④Collection<V> values()  :获取所有的value值

举个例子:

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建Map对象
 4         HashMap map=new HashMap();
 5         map.put(1,"a");
 6         map.put(2,"b");
 7         map.put(3,"c");
 8 
 9         //根据指定的key获取对应的值
10         Object o = map.get(1);
11         System.out.println("key为1对应的值" + o);
12         //如果指定的key存在,则获取对应的value值,否则defaultValue值
13         Object value = map.getOrDefault(8, "0");//8这个key值是不存在的
14         System.out.println("key为8对应的值" + value);
15 
16         //获取map中所有的key
17         Set set = map.keySet();
18         System.out.println("map中所有的key:" + set);
19 
20         //获取map中所有的value值
21         Collection values = map.values();
22         System.out.println("map中所有的value:" + values);
23     }
24 }

效果展示:

遍历元素

HashMap有两种遍历的方法,一种是根据key遍历,另一种是使用增强循环

方法一:根据key遍历

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建Map对象
 4         HashMap map=new HashMap();
 5         map.put(1,"a");
 6         map.put(2,"b");
 7         map.put(3,"c");
 8 
 9         //遍历
10         //1.获取map中所有的key
11         Set set = map.keySet();
12         //2.遍历key
13         for(Object key:set){
14             //3.根据key值获取map对应的value
15             Object value = map.get(key);
16             System.out.println(key+"---->" + value);
17         }
18     }
19 }

效果展示:

 方法二:使用增强循环遍历

 1 public class Test {
 2     public static void main(String[] args) {
 3         //创建Map对象
 4         HashMap map=new HashMap();
 5         map.put(1,"a");
 6         map.put(2,"b");
 7         map.put(3,"c");
 8 
 9         //1.获取map中的所有元素
10         Set<Map.Entry> set = map.entrySet();
11         for(Map.Entry entry:set){
12             //遍历获取key以及对应的value
13             System.out.println(entry.getKey()+"----->"+entry.getValue());
14         }
15     }
16 }

效果展示:

可以看见两者都可以遍历出map中的所有键值对,但是第一种方法是阿里巴巴不推荐使用的方法。因为它需要循环遍历两次map集合性能上比第二种方法要得多,所以在开发的时建议使用第二种方法

HashMap底层原理

jdk1.7之前,HashMap底层使用的是数组+链表。而且链表是通过头部插入数据

jdk1.8之后,HashMap底层使用的是数组+链表+红黑树。而且链表是通过尾部插入数据

将(key1,value1)添加到map中过程:

①首先需要调用key1所在类的hashCode()方法计算出key1对应的哈希值1,此时哈希值1仍需要经过hash()之后获取哈希值2

哈希值2再经过indexFor()之后确定(key1,value1)在数组table中的索引位置 i 

      1.1  如果索引位置 i 的数组上没有元素时,则(key1,value1)添加成功  ----------->情况1

      1.2  如果索引位置 i 的数组上存在元素(key2,value2),则需要比较key1和key2的哈希值2  ------------>哈希冲突

             2.1  如果key1的哈希值2与哈希值2不相同,则(key1,value2)添加成功 -------->情况2

             2.2  如果key1的哈希值2与哈希值2相同,则需要继续比较key1和key2的equals()方法。-------------->哈希冲突

                   3.1  如果调用equals()方法返回false:则(key1,value1)添加成功  --------->情况3 

                   3.2  如果调用的equals()方法返回true:则认为key1和key2是相同的。这种情况下,value1替换为原有的value2

说明:情况1,将(key1,value1)存放到数组的索引 i 位置

   情况2,情况3(key1,value1)元素与现有的(key2,value2)构成单向链表结构

 HashMap通过链表和红黑树解决hash冲突的问题,当hash冲突少时使用链表。当数组索引位置上hash冲突多时 [个数超过8数组长度大于64位],把链表变成红黑树

如果数组索引位置上hash冲突少于6个时,将把红黑树转换成链表