关键词搜索

源码搜索 ×
×

一篇文章带你搞定 Java 中 Map 接口的学习

发布2020-02-16浏览747次

详情内容

一、Map 接口简介

Collection、Set、List 接口都属于单值的操作,即每次只能操作一个对象,而 Map 与每次操作的是一对对像,即二元偶对象,Map 中的每个元素都使用 key->value 的形式存储在集合中。
Map 接口的定义:

public interface Map<K,V>

    在 Map 上也应用了泛型,必须同时设置好 key 或 value 的类型,在 Map 中每一对
    key -> value都表示一个值。Map 接口中方法:
    在这里插入图片描述

    二、Map.Entry 接口简介

    Map.Entry 是 Map 内部定义的一个接口,专门用来保存 key->value 的内容。定义如下:

    public static interface Map.Entry<K,V>
    

      Map.Entry 是使用 static 关键字声明的内部接口,此接口可以由外部通过“外部类.内部类”的形式直接调用。
      Map.Entry 接口的常用方法:
      在这里插入图片描述
      在 Map 操作中,所有的内容都是通过 key->value 的形式保存数据,对于集合来讲实际上是将 key->value 的数据保存在 Map.Entry 的实例之后,再在 Map 集合中插入的是一个 Map.Entry 的实例化对象:
      在这里插入图片描述
      Map.Entry在集合输出时会使用到

      三、 相关操作实例

      如果要想使用 Map 接口也必须依靠其子类实例化,Map接口中常用的子类:

      HashMap:无序存放,是新的操作类,key 不允许重复
      Hashtable:无序存放,是旧的操作类,key 不允许重复
      TreeMap:可以排序的 Map 集合,按集合中的 key 排序,key 不允许重复
      WeakHashMap:弱引用的 Map 集合,当集合中的某些内容不再使用时清除掉无用的数据,使用 gc 进行回收
      IdentifyHashMap:key 可以重复的 Map 集合
      
        2
      • 3
      • 4
      • 5

      HashMap 本身是 Map 的子类,直接使用此类为 Map 接口实例化即可

      1. 实例操作一:向集合中增加和取出内容

      在 Map 接口中可以使用 put(Object key,Object value) 方法向集合中增加内容,之后可以使用 get(E key) 方法根据 key 找出其对应的 value。

      public class Root{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("1","Java");
              map.put("https://files.jxasp.com/image/2","Python");
              String val = map.get("https://files.jxasp.com/image/2");//根据 key 求出 value
              System.out.println("取出的内容是:" + val);
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

      2. 实例操作二:判断指定的 key 或 value 是否存在

      如果要判断某一个指定的额 key 或 value 是否存在,可以使用 Map 接口中提供的 containsKey(Object key) 和 containsValue(Object value) 两个方法,前者判断Map集合是否存在指定的 key,后者判断 Map 集合是否存在指定的 value

      public class Root{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("1","Java");
              map.put("https://files.jxasp.com/image/2","Python");
              if (map.containsKey("1")) {
                  System.out.println("搜索的 key 存在!");
              }
              if (map.containsValue("Python")) {
                  System.out.println("搜索的 Value 存在!");
              }
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13

      3. 实例操作三:输出全部的 key

      在 Map 中提供了一个叫做 keySet() 的方法,可以将一个 Map 中的全部 key 变为一个 Set 集合,一旦有了 Set 实例,就可以直接使用 Iterator 输出。但是在进行操作时一定要注意接收的 Set 集合中指定的泛型要和 Map 中的key的泛型类型保持一致

      public class Root{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("1","Java");
              map.put("https://files.jxasp.com/image/2","Python");
              Set<String > keys = map.keySet();//得到全部的 key
              Iterator<String> iter = keys.iterator();
              System.out.print("全部的 key:");
              while (iter.hasNext()){
                  String  str = iter.next();
                  System.out.print(str + "、");
              }
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      4. 实例操作四:输出全部的 value

      如果要输出全部的 value,则使用 values() 方法,此方法的返回类型是 Collection,在进行操作时也同样需要注意泛型的类型

      public class Root{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("1","Java");
              map.put("https://files.jxasp.com/image/2","Python");
              Collection<String > values = map.values();//得到全部的 key
              Iterator<String> iter = values.iterator();
              System.out.print("全部的 value:");
              while (iter.hasNext()){
                  String  str = iter.next();
                  System.out.print(str + "、");
              }
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14

      四、排序的子类:TreeMap

      TreeMap 的主要功能是按 key 排序

      import java.util.*;
      
      public class Root{
          public static void main(String[] args) {
              Map<String,String > map = new TreeMap<String, String>();//实例化 map
              map.put("https://files.jxasp.com/image/2","Java");
              map.put("1","Python");
              map.put("3","Html");
              Set<String > keys = map.keySet();//得到全部的 key
              Iterator<String> iter = keys.iterator();
              while (iter.hasNext()){
                  String  str = iter.next();
                  System.out.println(str + " --> " + map.get(str));//取出 key 对应的内容
              }
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      在这里插入图片描述
      这里需要注意使用自定义类作为 key 类需要实现 Comparable 接口
      因为程序中国使用的是String作为 key ,因为String 本身已经实现了 Comparable 接口,所以可以直接执行,而如果使用一个自定义的类作为 key,则此类必须实现 Comparable 接口,否则将出现类转换异常。

      五、弱引用类:WeakHashMap

      无论是 HashMap 还是TreeMap 都是使用强引用保存的,即里面的内容不管是否使用都始终在集合中保留,如果希望集合自动清理暂时不用的数据就使用 WeakHashMap类。这样当进行垃圾收集时会释放掉集合中的垃圾信息
      WeakHashMap 的定义:

      public class WeakHashMap<K,V> extends AbstractMap<K,V>
      implements Map<K,V>
      
        2
      public class Test{
          public static void main(String[] args) {
              Map<String,String > map = new WeakHashMap<String, String>();//实例化 map
              map.put("https://files.jxasp.com/image/2","Java");
              map.put(new String("1"),new String("Python"));
              System.gc();//进行垃圾收集
              map.put("3","Html");
              System.out.println("内容:" + map);
              }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10

      在这里插入图片描述
      可以看出使用 map.put()的方式不同,会达到不同的强引用和弱引用效果

      六、Map 接口的使用注意事项

      1. 不能直接使用迭代输出 Map 的全部内容

      对于 Map 接口来说,其本身是不能直接使用迭代(Iterator、foreach)进行输出的,因为 Map 中的每个位置存放的是一对值(key->value),而 Iterator 中每次只能找到一个值
      所以,如果非要使用迭代进行输出,必须按照以下步骤(以 Iterator 输出方法为例):
      (1)将 Map 的实例通过 entrySet() 方法变为 Set 接口
      (2)通过 Set 接口实例为 Iterator 实例化
      (3)通过 Iterator 迭代输出,每个内容都是 Map.Entry 的对象
      (4)通过 Map.Entry 进行 key->value 的分离

      Map 一般很少直接输出,只是作为查询使用,而 Collection 接口在开发中主要作用是传递内容及输出。

      (1)使用 Iterator 输出 Map 实例

      public class Test{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("https://files.jxasp.com/image/2","Java");
              map.put("1","Python");
              map.put("3","Html");
              Set<Map.Entry<String ,String >> allSet = null;//声明一个 Set 集合,指定泛型
              allSet = map.entrySet();//将 Map 接口实例变为 Set 接口实例
              Iterator<Map.Entry<String ,String >> iter = null;//声明 Iterator 对象
              iter = allSet.iterator();//实例化 Iterator 对象
              while (iter.hasNext()){
                  Map.Entry<String ,String > me = iter.next();//找到 Map.Entry 实例
                  System.out.println(me.getKey() + "-->" + me.getValue());//输出 key 和 value
              }
              }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16

      在这里插入图片描述

      (2)使用 foreach 输出 Map 实例

      public class Test{
          public static void main(String[] args) {
              Map<String,String > map = new HashMap<String, String>();//实例化 map
              map.put("https://files.jxasp.com/image/2","Java");
              map.put("1","Python");
              map.put("3","Html");
              for (Map.Entry<String ,String> me:map.entrySet()){//输出 Set 集合
                  System.out.println(me.getKey() + "-->" + me.getValue());
              }
              }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11

      2. 直接使用非系统类作为 key

      如果使用一个自定义的对象表示 Map 中的 key,则对象所在的类中一定要覆写 equals() 和 hashCode() 方法,否则无法找到对应的 value

      import java.util.HashMap;
      import java.util.Map;
      
      class Person{
          private String name;
          private int age;
          public Person(String name,int age){
              this.name = name;
              this.age = age;
          }
          public boolean equals(Object obj){//覆写 equals() 方法
              if (this ==obj){
                  return true;
              }
              if (!(obj instanceof Person)){//传递进来的不是本类的对象
                  return false;
              }
              Person p = (Person)obj;
              if (this.name.equals(p.name) && this.age == p.age){
                  return true;//属性依次比较,相等返回
              }else {
                  return false;
              }
          }
          public int hashCode(){//覆写 hashCode() 方法
              return this.name.hashCode() * this.age;//计算公式
          }
          public String toString(){
              return "姓名" + this.name + ";年龄:" + this.age;//返回信息
          }
      }
      public class Test{
          public static void main(String[] args) {
              Map<Person,String> map = null;
              map = new HashMap<Person,String >();//实例化 Map 对象
              Person per = new Person("Java",30);
              map.put(per,"Python");
              System.out.println(map.get(per));
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40

      七、key 可以重复的 Map 集合:IdentityHashMap

      前面所述的 Map 操作中 key 的值是不能重复的,如果重复会覆盖之前的内容,此时可以使用 IdentityHashMap,使用此类只有地址不相等(key1 != key2),就表示不是重复的 key,可以添加到集合中。

      public class Test{
          public static void main(String[] args) {
              Map<Person,String> map = new IdentityHashMap<Person,String >();
              map.put(new Person("张三",30),"J1");
              map.put(new Person("李四",31),"J2");
              map.put(new Person("李四",31),"J3");
              map.put(new Person("王二",32),"J4");
              Set<Map.Entry<Person,String >> allSet = null;//声明一个 Set 集合
              allSet = map.entrySet();//将 Map 接口实例为 Set 接口实例
              Iterator<Map.Entry<Person,String >> iter = null;
              iter = allSet.iterator();//实例化 Iterator 对象
              while (iter.hasNext()){
                  Map.Entry<Person,String > me = iter.next();//每个对象都是 Map.Entry 实例
                  System.out.println(me.getKey() + "-->" + me.getValue());//输出 key 和 value
              }
          }
      }
      
        2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      相关技术文章

      点击QQ咨询
      开通会员
      返回顶部
      ×
      微信扫码支付
      微信扫码支付
      确定支付下载
      请使用微信描二维码支付
      ×

      提示信息

      ×

      选择支付方式

      • 微信支付
      • 支付宝付款
      确定支付下载