Map+可变参数+Debug调试

一.Map

1.1 概述

  1. 现实生活中,我们常会看到这样的一种集合:IP地址与主机名,身份证号与个人,系统用户名与系统用户对象等,这种一一对应的关系,就叫做映射。Java提供了专门的集合类用来存放这种对象关系的对象,即java.util.Map 接口。

  2. 我们通过查看 Map 接口描述,发现 Map 接口下的集合与 Collection 接口下的集合,它们存储数据的形式不同

    • Collection接口 定义了 单列集合规范,每次存储一个元素 单个元素–>单身集合Collection

    • Map接口,定义了双列集合的规范,每次存储一对儿元素–>夫妻对集合Map<K,V>,K代表键的类型,V代表值的类型。

      • Collection 中的集合,元素是孤立存在的(理解为单身),向集合中存储元素采用一个个元素的方式存储。Map 中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。
      • Collection 中的集合称为单列集合, Map 中的集合称为双列集合。
      • 需要注意的是, Map 中的集合不能包含重复的键,值可以重复;每个键只能对应一个值。

1.2 Map的常用子类

  1. 通过查看Map接口描述,看到Map有多个子类,这里我们主要讲解常用的HashMap集合、LinkedHashMap集合。

  2. HashMap:存储数据采用的哈希表结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

  3. LinkedHashMap:HashMap下有个子类LinkedHashMap,存储数据采用的哈希表结构+链表结构。通过链表结构可以保证元素的存取顺序一致;通过哈希表结构可以保证的键的唯一、不重复,需要重写键的
    hashCode()方法、equals()方法。

  4. Map集合的特点:

    • Map集合是一个双列集合,一个元素由两个值组成(key,value)
    • Map集合中key是不允许重复的,value可以重复
    • Map集合中key的数据类型和value的数据类型可以相同,也可以不同
    • Map集合中key和value是一一对应
    • java.util.HashMap<k,v>集合 implements Map<k,v>接口
  5. HashMap集合的特点:

    • HashMap底层使用的是哈希表结构

      • jdk1.8之前:数组+单向链表

      • jdk1.8之后:数组+单向链表/数组+红黑树

    • 是一个无序的集合,存储的元素和取出的元素顺序有可能不一致,自然元素会有序排序

1.3 Map的常用方法

  1. Map接口中定义了很多方法,常用的如下:

    • public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。

      /*
         public V put(K key, V value):  把指定的键与指定的值添加到Map集合中。
          key不重复,v返回null,key重复,会使用新的value替换之前的value,返回被替换的value
      */ 		
      		//创建Map集合对象
              Map<String,String> map = new HashMap<>();
              //使用put方法往Map集合中添加元素
              String v1 = map.put("杨过", "小龙女");
              System.out.println("v1:"+v1);//v1:null
              String v2 = map.put("郭靖", "黄蓉");
              System.out.println("v2:"+v2);//v2:null
              String v3 = map.put("尹志平","小龙女");
              System.out.println("v3:"+v3);//v3:null
              String v4 = map.put("杨过", "大雕");
              System.out.println("v4:"+v4);//v4:小龙女
              System.out.println(map);//{杨过=大雕, 尹志平=小龙女, 郭靖=黄蓉}
      
    • public V remove(Object key) : 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。

      /*
       public V remove(Object key) 根据指定的key,删除对应的键值对
         	key存在,返回被删除的value,key不存在,返回null
      */		
      		Map<String,Integer> map = new HashMap<>();
              map.put("a",1);
              map.put("b",2);
              map.put("d",4);
              map.put("c",3);
              System.out.println(map);//{a=1, b=2, c=3, d=4}
              Integer v1 = map.remove("c");
              System.out.println("v1:"+v1);//v1:3
              Integer v2 = map.remove("w");
              System.out.println("v2:"+v2);//v2:null
      		int v3 = map.remove("s");
              System.out.println("v3:"+v3);//v3:空指针异常,进行了拆箱操作
              System.out.println(map);//{a=1, b=2, d=4}
      
    • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

       /*
          public V get(Object key)通过key获取value,key不存在,value返回null
       */	   
      		Map<String,Integer> map = new HashMap<>();
              map.put("a",1);
              map.put("b",2);
              map.put("d",4);
              map.put("c",3);
              Integer v1 = map.get("a");
              System.out.println("v1:"+v1);//v1:1
              Integer v2 = map.get("q");
              System.out.println("v2:"+v2);//v2:null
      
    • public Set keySet() : 获取Map集合中所有的键,存储到Set集合中。

    • public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。

    • public boolean containKey(Object key) :判断该集合中是否有此键。

      /*
        public boolean containKey(Object key):判断该集合中是否有此键。
         boolean containsValue(Object value)  判断该集合中是否有此值。
         包含:返回true; 不包含:返回false
       */
      		Map<String,Integer> map = new HashMap<>();
              map.put("a",1);
              map.put("b",2);
              map.put("d",4);
              map.put("c",3);
              boolean b1 = map.containsKey("d");
              System.out.println("b1:"+b1);//b1:true
              boolean b2 = map.containsKey("e");
              System.out.println("b2:"+b2);//b2:false
              System.out.println(map.containsValue(4));//true
              System.out.println(map.containsValue(5));//false
      

1.4 Map的遍历

方式1:键找值方式

  1. 通过元素中的键,获取键所对应的值分析步骤:

    • Set keySet() 返回此映射中包含的键的 Set 视图。

    • 实现步骤:

      • 使用Map集合中的方法keySet,把所有的key取出来存储到一个Set集合中
      • 遍历Set集合,获取Map集合的每一个key
      • 使用Map集合中的方法get(key),通过key找到value
        在这里插入图片描述
    HashMap<String,Integer> map = new HashMap<>();
            map.put("张三",20);
            map.put("李四",30);
            map.put("老王",50);
            //1.使用Map集合中的方法keySet,把所有的key取出来存储到一个Set集合中
            Set<String> set = map.keySet();
            //2.遍历Set集合,获取Map集合的每一个key
            //使用迭代器遍历Set集合
            Iterator<String> it = set.iterator();
            while(it.hasNext()){
                String key = it.next();
                //3.使用Map集合中的方法get(key),通过key找到value
                Integer value = map.get(key);
                System.out.println(key+"="+value);
            }
            System.out.println("--------------------------");
            //使用增强for遍历Set集合
            for(String key : map.keySet()){
                Integer value = map.get(key);
                System.out.println(key+"="+value);
         }
    

方式2:键值对方式

  1. 即通过集合中每个键值对(Entry)对象,获取键值对(Entry)对象中的键与值。

  2. Entry键值对对象:

    • 我们已经知道, Map 中存放的是两种对象,一种称为key(键),一种称为value(值),它们在在 Map 中是一一对应关系,这一对对象又称做 Map 中的一个 Entry(项) 。 Entry 将键值对的对应关系封装成了对象。即键值对对象,这样我们在遍历 Map 集合时,就可以从每一个键值对( Entry )对象中获取对应的键与对应的值。

    • Map的遍历_通过键值对的方式

    • Map集合中的方法:

    • Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的 Set 视图。

    • public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的键值对对象的集合(Set集合)。获取了Entry对象 , 表示获取了一对键和值,那么同样Entry中 , 分别提供了获取键和获取值的方法:

    • public K getKey() :获取Entry对象中的键。

    • public V getValue() :获取Entry对象中的值。

    • 实现步骤:

      • 使用Map集合中的方法entrySet,把所有的Entry对象取出来,存储到一个Set集合中
      • 遍历Set集合,获取每一个Entry对象
      • 使用Entry对象中的方法getKey和getValue获取键与值
        在这里插入图片描述
       		HashMap<String,Integer> map = new HashMap<>();
              map.put("张三",20);
              map.put("李四",30);
              map.put("老王",50);
              //1.使用Map集合中的方法entrySet,把所有的Entry对象取出来,存储到一个Set集合中
              Set<Map.Entry<String, Integer>> set = map.entrySet();
              //2.遍历Set集合,获取每一个Entry对象
              //使用迭代器遍历Set集合
              Iterator<Map.Entry<String, Integer>> it = set.iterator();
              while(it.hasNext()){
                  Map.Entry<String, Integer> entry = it.next();
                  //3.使用Entry对象中的方法getKey和getValue获取键与值
                  String key = entry.getKey();
                  Integer value = entry.getValue();
                  System.out.println(key+"="+value);
              }
              System.out.println("-----------------");
              //使用增强for遍历Set集合
              for (Map.Entry<String, Integer> entry : set) {
                  //3.使用Entry对象中的方法getKey和getValue获取键与值
                  String key = entry.getKey();
                  Integer value = entry.getValue();
                  System.out.println(key+"="+value);
              }
      
    • 操作步骤与图解:

      • 获取Map集合中,所有的键值对(Entry)对象,以Set集合形式返回。方法提示: entrySet() 。
      • 遍历包含键值对(Entry)对象的Set集合,得到每一个键值对(Entry)对象。
      • 通过键值对(Entry)对象,获取Entry对象中的键与值。 方法提示: getkey() getValue()
      • Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了

1.5 HashMap存储自定义类型

  1. HashMap集合如何保证key不重复
  • 作为Key元素必须重写hashCode和equals方法
/*
        HashMap存储自定义类型
        key:Person
        value:String
        Person类需要重写hashCode和equals方法,以保证同名同年龄的是视为同一个人
     */
//创建HashMap集合,存储Person
        HashMap<Person,String> map = new HashMap<>();
        map.put(new Person("小明",18),"中国");
        map.put(new Person("汤姆",18),"英国");
        map.put(new Person("阿里",6),"朝鲜");
        map.put(new Person("普哥",28),"俄罗斯");
        map.put(new Person("女王",18),"毛里求斯");
        //遍历Map集合,使用entrySet+增强for
        Set<Map.Entry<Person, String>> set = map.entrySet();
        for (Map.Entry<Person, String> entry : set) {
            //使用Entry对象中的方法getKey和getValue获取键与值
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key+"-->"+value);
        }

1.6 LinkedHashMap介绍

  1. 在HashMap下面有一个子类LinkedHashMap,它是链表和哈希表组合的一个数据存储结构。

  2. java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合
    LinkedHashMap特点
    LinkedHashMap底层是哈希表+单向链表–>双向链表
    LinkedHashMap里边存储的元素是有序的

     HashMap<String,String> map = new HashMap<>();
            map.put("aaa","111");
            map.put("ccc","222");
            map.put("ddd","333");
            map.put("bbb","444");
            map.put("aaa","555");
            System.out.println(map);//key不允许重复,value可以重复;是一个无序的集合 {aaa=555, ccc=222, bbb=444, ddd=333}
    
            LinkedHashMap<String,String> linked = new LinkedHashMap<>();
            linked.put("aaa","111");
            linked.put("ccc","222");
            linked.put("ddd","333");
            linked.put("bbb","444");
            linked.put("aaa","555");
            System.out.println(linked);//key不允许重复,value可以重复;是一个有序的集合 {aaa=555, ccc=222, ddd=333, bbb=444}
    
  3. HashTable(了解即可)

    • java.util.Hashtable<k,v>集合 implements Map<k,v>
      • Hashtable是一个最早期的双列集合,在jdk1.0版本就存在了
      • Hashtable底层也是一个哈希表
  • Hashtable是一个线程安全的集合,是一个单线程的集合,效率低
    • HashMap是一个线程不安全的集合,是一个多线程的集合,效率高
    • Hashtable不允许存储null键null值,会抛出异常
    • HashMap允许存储null键null值
    • Hashtable效率低所以被HashMap个取代了,但是Hashtable的子类Properties集合依然活跃在历史的舞台
HashMap<String,String> map = new HashMap<>();
        map.put(null,"a");//map.put("null","a");
        map.put("b",null);
        map.put(null,null);
        System.out.println(map);//{null=null, b=null}

        Hashtable<String,String> table = new Hashtable<>();
        //table.put(null,"a");//NullPointerException
        //table.put("b",null);//NullPointerException
        //table.put(null,null);//NullPointerException

1.7 Map集合练习

  1. 练习_计算一个字符串中每个字符出现的次数

  2. 分析:

    • 使用Scanner获取一个字符串

    • 定义一个HashMap集合key存储每种字符,value存储字符个数

    • 遍历字符串,获取字符串中的每一个字符

      • 可以使用String类中的方法toCharArray,把字符串转换为一个字符数组
      • 可以使用String类中的方法charAt(i)+length()
    • 使用获取到字符,根据Map集合的方法containKey,判断Map集合中是否包含指定的字符

      • true:字符存在
        • 使用Map集合中的get方法,根据key获取value(字符个数)
        • value++
        • put(字符,value)
      • false:字符不存在
        • put(字符,1)
    • 遍历集合,查看结果
      在这里插入图片描述

     //1.使用Scanner获取一个字符串
            System.out.println("请输入一个字符串:");
            String s = new Scanner(System.in).next();
            //2.定义一个HashMap集合key存储每种字符,value存储字符个数
            HashMap<Character,Integer> map = new HashMap<>();
            //3.遍历字符串,获取字符串中的每一个字符
            for(int i=0; i<s.length(); i++){
                char key = s.charAt(i);
                //4.使用获取到字符,根据Map集合的方法containKey,判断Map集合中是否包含指定的字符
                if(map.containsKey(key)){
                    //true:字符存在
                    //a.使用Map集合中的get方法,根据key获取value(字符个数)
                    Integer value = map.get(key);
                    //b.value++
                    //c.put(字符,value)
                    map.put(key,++value);
                }else{
                    //false:字符不存在 put(字符,1)
                    map.put(key,1);
                }
            }
            //5.遍历集合,查看结果
            System.out.println(map);
    

二.补充知识点

2.1 可变参数

  1. 是JDK 1.5 之后出现的,底层是一个数组,会根据传递的参数个数不同,而创建长度不同的数组,来接收这些参数

  2. 作用:当我们定义方法的时候,方法参数的数据类型已经确定了,但是参数的个数不确定,就可以使用可变参数

  3. 格式:

    修饰符 返回值类型 方法名(数据类型...变量名){
    		方法体
    }
    
  4. 可变参数的底层原理:

    • 数据类型…变量名:传递参数的个数可以是任意个(0,1,2,…n)
    /*
           定义一个计算n个int类型整数和的方法
           方法参数的数据类型已经确定就是int类型
           但是参数的个数不确定,所以就可以使用可变参数
           getSum();就会创建一个长度为0的数组,存储参数 int[] arr = new int[]{};
           getSum(10);就会创建一个长度为1的数组,存储参数 int[] arr = new int[]{10};
           getSum(10,20);就会创建一个长度为2的数组,存储参数 int[] arr = new int[]{10,20};
           getSum(10,20,30,40,50,60,70,80,90,100);就会创建一个长度为10的数组,存储参数 		   int[] arr = new int[]{10,20,30,40,50,60,70,80,90,100};
        */
     public static int getSum(int...arr){
            //System.out.println(arr);//[I@50cbc42f 数组地址值
            //System.out.println(arr.length);
            //定义一个变量,初始值为0,记录累加求和
            int sum = 0;
            //遍历数组,获取数组中的每一个元素
            for (int i : arr) {
                //累加求和
                sum += i;
            }
            //把和返回
            return sum;
        }
    
  5. 可变产生的注意事项:

    • 一个参数列表中,只能包含一个可变参数

      public static void method(int...a,String...b){}
      
    • 参数列表中有多个参数,可变参数需要写在末尾

      public static void method(int a,String s,double d,String...arr){}
      
    • 可变参数的终极写法

      public static void method(Object...o){}
      

2.2 Idea开发工具的Debug追踪

  1. debug:断点调试

    • 作用:

      • 可以查看程序执行的流程
      • 可以调试程运行过程中出现的一些问题
    • 使用步骤:

      • 在行号的右边,鼠标左键单击增加一个断点(每个方法的第一行)
      • 右键–>debug
      • 程序就会停止到添加的第一个断点处
        在这里插入图片描述
    • 快捷键:

      • f8:逐行执行代码
      • f7:进入到方法中
      • shift+f8:跳出方法
      • f9:跳到下一个断点
      • ctry+f2:停止debug,也会停止程序
      • console:切换到控制台(控制台打印的内容)
      • variables:显示程序中所有变量的区域

2.3 静态导入

  1. JDK1.5新特性,静态导入

    • 减少开发的代码量
    • 标准写法,导入包的时候才能使用
    • import static java.lang.System.out; 最末尾,必须是一个静态成员
    import java.util.ArrayList;
    import static java.lang.System.out;
    import static java.util.Collections.sort;
    
    public class Demo01StaticImport {
        public static void main(String[] args) {
            System.out.println(1);
            System.out.println(1);
            System.out.println(1);
            out.println(1);//静态导入
            out.println(1);
            out.println(1);
            ArrayList<Integer> list = new ArrayList<>();
            list.add(1);
            list.add(3);
            list.add(2);
            sort(list);//静态导入
            System.out.println(list);
        }
    }
    

2.4 集合嵌套

  1. 集合嵌套

    • 集合中的元素仍是一个集合
    • 集合可以随意嵌套(Map可以嵌套Collection,Collection也可以嵌套Map)
    //定义一个存储省份名称和城市的Map集合
            Map<String,ArrayList<String>> map = new HashMap<>();
            //创建存储城市的ArrayList集合
            ArrayList<String> hb = new ArrayList<>();
            hb.add("石家庄");
            hb.add("张家口");
            hb.add("承德");
            hb.add("邯郸");
    
            ArrayList<String> nmg = new ArrayList<>();
            nmg.add("呼和浩特");
            nmg.add("包头");
            nmg.add("锡林郭勒");
            nmg.add("赤峰");
    
            ArrayList<String> gd = new ArrayList<>();
            gd.add("深圳");
            gd.add("广州");
            gd.add("东莞");
            gd.add("中山");
    
            //把省份名称和存储城市的ArrayList集合添加到Map中
            map.put("河北省",hb);
            map.put("内蒙古",nmg);
            map.put("广东省",gd);
    
            //遍历Map集合:keySet+增强for
            Set<String> set = map.keySet();
            for (String key : set) {
                //通过key获取value
                ArrayList<String> value = map.get(key);
                //继续遍历ArrayList集合
                  System.out.println(key+"-->"+value);
    //            for (String cityName : value) {
    //                System.out.println(key+"-->"+cityName);
    //            }
              }
    /*打印出:
    内蒙古-->[呼和浩特, 包头, 锡林郭勒, 赤峰]
     广东省-->[深圳, 广州, 东莞, 中山]
     河北省-->[石家庄, 张家口, 承德, 邯郸]
     */
    
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值