02_Java语音进阶||day04_Map,JDK9对集合添加的优化(of方法)、Debug追踪、斗地主案例

第一章 Map集合

1.1 概述

  1. java.util.Map<k, v>集合
  2. Map集合的特点:
    1. Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
    2. Map集合中的元素,key和value的数据类型可以相同,也可以不同
    3. Map集合中的元素,key是不允许重复的,value是可以重复的
    4. Map集合中的元素,key和value是一一对应的

1.2 Map常用的实现类

  1. java.util.HashMap<k, v>集合 implements ++Map++<k, v>接口
  2. HashMap集合的特点
    1. HashMap集合底层是哈希表:查询速度快
      • JDK1.8之前:数组+单向链表
      • JDK1.8之后:数组+单向链表/红黑树(链表的长度超过8)–>提高查询速度
    2. HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
  3. java.util.LinkedHashMap<k, v>集合 extends ++HashMap++<k, v>集合
  4. LinkedHashMap集合的特点
    1. LinkedHashMap集合底层是哈希表 + 链表:保证迭代的顺序
    2. LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

1.3 Map接口中的常用方法

  1. V put(K key, V value)
    • 将指定的值与此映射中的指定键关联(可选操作)。
    • 注:
      • 存储键值对的时候,key不重复,返回值V是null
      • 存储键值对的时候,key重复,会使用新的value替换Map中重复的value,返回被替换的【!】value
  2. V remove(Object key)
    • 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。
    • 注:
      • key存在,V返回被删除的值
      • key不存在,v返回null
      • Integer也可以int接收(自动拆箱),但是如果没有对应key就会空指针异常
  3. V get(Object key)
    • 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null。
    • 注:
      • key存在,返回对应value值
      • key不存在,v返回null
  4. boolean containsKey(Object key)
    • 如果此映射包含指定键的映射关系,则返回 true。
    • 注:
      • 包含key存在,true
      • 不包含key不存在,false
  5. Set keySet()
    • 返回此映射中包含的键的 Set 视图。
  6. Set<Map.Entry<K,V>> entrySet()
    • 返回此映射中包含的映射关系的 Set 视图。
    public class Demo01Map {
        public static void main(String[] args) {
            //show01();
            //show02();
            //show03();
            show04();
        }
    
        //containsKey方法
        private static void show04() {
            Map<String, Integer> map = new HashMap<>();
            map.put("李晨", 185);
            map.put("陈赫", 165);
            map.put("邓超", 175);
            boolean b1 = map.containsKey("李晨");
            System.out.println(b1); //true
            boolean b2 = map.containsKey("郑凯");
            System.out.println(b2); //false
        }
    
        //get方法
        private static void show03() {
            Map<String, Integer> map = new HashMap<>();
            map.put("李晨", 185);
            map.put("陈赫", 165);
            map.put("邓超", 175);
            Integer v1 = map.get("陈赫");
            System.out.println(v1); //165
        }
    
        //remove方法
        private static void show02() {
            Map<String, Integer> map = new HashMap<>();
            map.put("李晨", 185);
            map.put("陈赫", 165);
            map.put("邓超", 175);
            System.out.println(map);    //{邓超=175, 陈赫=165, 李晨=185}
            Integer v1 = map.remove("邓超");  //int接收也行(自动拆箱),但是如果没有对应key就会空指针异常
            System.out.println(v1); //175
            System.out.println(map);    //{陈赫=165, 李晨=185}
        }
    
        //put方法
        private static void show01() {
            Map<String, String> map = new HashMap<>();
            String put1 = map.put("李晨", "范冰冰1");
            System.out.println(put1);   //null
    
            String put2 = map.put("李晨", "范冰冰2");
            System.out.println(put2);   //范冰冰1
    
            map.put("冷锋", "龙小云");
            System.out.println(map);    //{李晨=范冰冰2, 冷锋=龙小云}
        }
    }

1.4 Map接口遍历键找值方式

  1. Map集合的第一种遍历方式:通过键找值方式:
    • Map无法直接遍历,所以通过键找值得方式


2. Map集合中的方法:Set keySet()
* 返回此映射中包含的键的 Set 视图。
3. 实现步骤
1. 使用Map集合中的方法keySet(),把Map集合所有的key取出来存储到一个Set集合
2. 遍历Set集合,获取Map集合中的每一key
* 迭代器Iterator/增强for
3. 在遍历中,通过Map集合中的方法get(key),找到对应的value

    public static void main(String[] args) {
        Map<String, Integer> map = new HashMap<>();
        map.put("李晨", 185);
        map.put("陈赫", 165);
        map.put("邓超", 175);
        //1.keySet
        Set<String> setM = map.keySet();
        //2.遍历1和get连用
        Iterator<String> it = setM.iterator();
        while(it.hasNext()){
            String key = it.next();
            Integer value = map.get(key);
            System.out.println("key" + key + "value" + value);
        }
        System.out.println("========");
        //遍历2和get连用
        for (String s : setM) {
            Integer v = map.get(s);
            System.out.println("key=" + s + "value=" + v);
        }
    }
    
    //结果:
    key邓超value175
    key陈赫value165
    key李晨value185
    ========
    key=邓超value=175
    key=陈赫value=165
    key=李晨value=185

1.5 Entry键值对对象

  1. Map.Entry<K, V>:在Map接口中有一个内部接口Entry
  2. 作用:
    1. Map集合一创建,那么就会在Map集合中创建一个Entry对象用来记录键与值(键值对对象,键与值得映射关系)
      • 可看成:结婚证

1.6 Map集合遍历键值对方式

  1. Map集合的第二种遍历方式:使用Entry对象遍历
  2. Map集合中的方法:
    • Set<Map.Entry<K,V>> entrySet()
      • 返回此映射中包含的映射关系的 Set 视图。
  3. 实现步骤
    1. 使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来存储到一个Set集合
    2. 遍历Set集合,获取Map集合中的每一Entry对象
      • 迭代器Iterator/增强for
    3. 在遍历中,使用Entry对象中的方法getKey()和getValue()获取键与值

1.7 HashMap存储自定义类型键值

  1. Map集合保证key是唯一的:
    • 作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一
    public class Demo01HashMapSavePerson {
        public static void main(String[] args) {
            ///show01();
            show02();
        }
    
        //HashMap存储自定义类型键值
        //key:Person
        //value:String
        private static void show02() {
            HashMap<Person, String> mapH = new HashMap<>();
    
            mapH.put(new Person("张三", 18), "北京");
            mapH.put(new Person("李四", 18), "上海");
            mapH.put(new Person("张三", 21), "重庆");
            mapH.put(new Person("张三", 18), "北京");
    
            //使用entrySet
            Set<Map.Entry<Person, String>> setE = mapH.entrySet();
            for (Map.Entry<Person, String> pE : setE) {
                System.out.println("key=" + pE.getKey() + "value=" + pE.getValue());
            }
        }
    
        //HashMap存储自定义类型键值
        //key:String
        //value:Person
        private static void show01() {
            HashMap<String, Person> mapH = new HashMap<>();
    
            mapH.put("北京", new Person("张三", 18));
            mapH.put("上海", new Person("李四", 12));
            mapH.put("广州", new Person("王五", 21));
            mapH.put("北京", new Person("赵六", 26));   //key与上面重复了,所以会把张三替换掉
    
            //使用keySet——iterator
            Set<String> s1 = mapH.keySet();
            Iterator<String> it1 = s1.iterator();
            while (it1.hasNext()){
                String key = it1.next();
                Person value = mapH.get(key);
                System.out.println("key=" + key + "value" + value);
            }
            System.out.println("============");
            //使用keySet——for
            for (String s : s1) {
                Person v = mapH.get(s);
                System.out.println("key=" + s + "value=" + v);
            }
        }
    
    }
    
    //结果:
    show01()
        key=上海valuePerson{name='李四', age=12}
        key=广州valuePerson{name='王五', age=21}
        key=北京valuePerson{name='赵六', age=26}
        ============
        key=上海value=Person{name='李四', age=12}
        key=广州value=Person{name='王五', age=21}
        key=北京value=Person{name='赵六', age=26}
    show02()
        key=Person{name='张三', age=21}value=重庆
        key=Person{name='张三', age=18}value=北京
        key=Person{name='李四', age=18}value=上海

1.8 LinkedHashMap集合

  1. java.util.LinkedHashMap<K, V> extends HashMap<K, V>
  2. (API)Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
  3. 底层原理:
    • 哈希表 + 链接(记录元素的顺序)
    • 有序的集合
    public class Demo01LinkedHashMap {
        public static void main(String[] args) {
            //HashMap
            HashMap<String, String> mapH = new HashMap<>();
            mapH.put("a", "a");
            mapH.put("c", "c");
            mapH.put("b", "b");
            mapH.put("a", "d");
            System.out.println(mapH);   //无序
    
            //LinkedHashMap
            LinkedHashMap<String, String> mapL = new LinkedHashMap<>();
            mapL.put("a", "a");
            mapL.put("c", "c");
            mapL.put("b", "b");
            mapL.put("a", "d");
            System.out.println(mapL);   //有序
        }
    }
    
    //结果:
    {a=d, b=b, c=c}
    {a=d, c=c, b=b}

1.9 Hashtable集合

  1. java.util.Hashtable<K, v>集合 implements Map<K, v>集合
  2. Hashtable和HashMap区别一:
    1. Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
    2. HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程结合,速度快
  3. Hashtable和HashMap区别二:
    1. Hashtable集合不能存储null值,null键
    2. HashMap集合(之前学的所有集合):能存储null值,null键
  4. 和Vector(被ArrayList)集合一样,在jdk1.2之后被(HashMap)取代了
  5. Hashtable集合的子类Properties依然常用
    • Properties集合是一个唯一和IO流相结合的集合【将IO时候再来讲解】

1.10 Map集合练习


  1. 分析:
    1. 使用Scanner获取用户输入的字符串
    2. 创建Map集合,key是字符串中的字符,value是字符的个数
    3. 遍历字符串,获取每一个字符
    4. 使用获取到的字符,去Map集合判断key是否存在
      • key存在:
        1. 通过字符(key),获取value(字符个数)
        2. value++
        3. put(key,value)把新的value存储到Map集合中
      • key不存在:
        • put(key,1)
    5. 遍历Map集合,输出结果
    public static void main(String[] args) {
        //1. 使用Scanner获取用户输入的字符串
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = sc.next();

        //2. 创建Map集合,key是字符串中的字符,value是字符的个数
        HashMap<Character, Integer> mapH = new HashMap<>();

        //3. 遍历字符串,获取每一个字符
        for(char c : str.toCharArray()){
            //4. 使用获取到的字符,去Map集合判断key是否存在
            if(mapH.containsKey(c)){    //key存在的
                Integer value = mapH.get(c);
                value++;
                mapH.put(c, value);
            }else {
                mapH.put(c, 1);
            }
        }

        //5. 遍历Map集合,输出结果(这里使用entrySet方法——增强for)
        Set<Map.Entry<Character, Integer>> eS = mapH.entrySet();
        for (Map.Entry<Character, Integer> e : eS) {
            System.out.println("key:" + e.getKey() + " ,value:" + e.getValue());
        }
    }
    
    //结果:
    请输入一个字符串:
    aaavvjjjcccc
    key:a ,value:3
    key:c ,value:4
    key:v ,value:2
    key:j ,value:3

第二章 补充知识点

2.1 JDK9对集合添加的优化(of方法)

  1. JDK9的新特性:
    • List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素
    • static List of (E… elements)
    • 使用前提:
      • 当集合中存储的元素的个数已经确定了,不在改变时使用
  2. 注意:
    1. of方法只适用于List接口,Set接口,Map接口,不适用于接接口的实现类
    2. of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
    3. Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常
    public class Demo01JDK9 {
        public static void main(String[] args) {
            List<String> list = List.of("a", "b", "a", "c", "d");
            System.out.println(list);//[a, b, a, c, d]
            //list.add("w");//UnsupportedOperationException:不支持操作异常
    
            //Set<String> set = Set.of("a", "b", "a", "c", "d");//IllegalArgumentException:非法参数异常,有重复的元素
            Set<String> set = Set.of("a", "b", "c", "d");
            System.out.println(set);
            //set.add("w");//UnsupportedOperationException:不支持操作异常
    
            //Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20,"张三",19);////IllegalArgumentException:非法参数异常,有重复的元素
            Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);
            System.out.println(map);//{王五=20, 李四=19, 张三=18}
            //map.put("赵四",30);//UnsupportedOperationException:不支持操作异常
        }
    }

2.2 Debug追踪

  1. Debug调试程序:
    • 可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
  2. 使用方式:
    1. 在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)
    2. 右键,选择Debug执行程序
    3. 程序就会停留在添加的第一个断点处
  3. 执行程序:
    • f8:逐行执行程序
    • f7:进入到方法中
    • shift+f8:跳出方法
    • f9:跳到下一个断点,如果没有下一个断点,那么就结束程序
    • ctrl+f2:退出debug模式,停止程序
    • Console:切换到控制台

第三章 斗地主案例(有序版本)

3.1 案例介绍

3.2 案例分析

3.3 案例实现

    public class PokerTest {
        public static void main(String[] args) {
            //准备牌
            //存牌的索引和组装好的牌
            HashMap<Integer, String> poker = new HashMap<>();
            //存牌的索引
            ArrayList<Integer> pokerIndex = new ArrayList<>();
            //两个集合(JDK1.9的of)存储花色和牌号(这里用数组)
            String[] colors = {"♠", "♥", "♣", "♦"};
            String[] numbers = {"2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3"};
    /*        ArrayList<String> colors = new ArrayList<>();
            colors.add("♠");
            colors.add("♥");
            colors.add("♣");
            colors.add("♦");
            ArrayList<String> numbers = new ArrayList<>();
            numbers.add("2");
            numbers.add("A");
            numbers.add("K");
            numbers.add("Q");
            numbers.add("J");
            numbers.add("10");
            numbers.add("9");
            numbers.add("8");
            numbers.add("7");
            numbers.add("6");
            numbers.add("5");
            numbers.add("4");
            numbers.add("3");*/
    
            //把大王小王存储到集合中
            int index = 0;
            poker.put(index, "大王");
            pokerIndex.add(index);
            index++;
            poker.put(index, "小王");
            pokerIndex.add(index);
            index++;
    
            //循环嵌套来存储52张牌
            for (String number : numbers) {
                for (String color : colors) {
                    poker.put(index, number + color);
                    pokerIndex.add(index);
                    index++;
                }
            }
            //System.out.println(poker);
    
            //2洗牌,使用Collections中的shuffle方法打乱集合(pokerIndex)
            Collections.shuffle(pokerIndex);
    
            //3发牌:定义四个集合
            ArrayList<Integer> palyer01 = new ArrayList<>();
            ArrayList<Integer> palyer02 = new ArrayList<>();
            ArrayList<Integer> palyer03 = new ArrayList<>();
            ArrayList<Integer> diPai = new ArrayList<>();
    
            //遍历pokerIndex集合,获取每一个索引
            for (int i = 0; i < pokerIndex.size(); i++) {
                Integer in = pokerIndex.get(i);
                if(i >= 51){//发底牌
                    diPai.add(in);
                }else if(i % 3 == 0){//给玩家一
                    palyer01.add(in);
                }else if(i % 3 == 1){//给玩家二
                    palyer02.add(in);
                }else if(i % 3 == 2){//给玩家三
                    palyer03.add(in);
                }
            }
    
            //4排序Collections中的sort
            Collections.sort(palyer01);
            Collections.sort(palyer02);
            Collections.sort(palyer03);
            Collections.sort(diPai);
    
            //调用看牌方法lookPoker
            lookPoker("刘德华", poker, palyer01);
            lookPoker("周润发", poker, palyer02);
            lookPoker("周星驰", poker, palyer03);
            lookPoker("底牌", poker, diPai);
        }
    
        //定义一个看牌方法
    //    参数:
    //    String name:玩家名称
    //    HashMap<Integer,String> poker:存储牌的poker集合
    //    ArrayList<Integer> list:存储玩家和底牌的List集合
    //    查表法:
    //    遍历玩家或者底牌集合,获取牌的索引
    //            使用牌的索引,去Map集合中,找到对应的牌
        public static void lookPoker(String name, HashMap<Integer, String> poker, ArrayList<Integer> list){
            //输出玩家名称:
            System.out.println("name:" + name);
    
            //遍历玩家或底牌,获取索引
            for (Integer key : list) {
                String value = poker.get(key);
                System.out.print(value + " ");
            }
            System.out.println();
        }
    }
    
    //结果:
    name:刘德华
    2♦ A♦ K♥ K♦ Q♦ J♠ 10♦ 9♥ 9♦ 8♥ 7♠ 7♥ 7♦ 6♦ 5♦ 4♥ 3♦ 
    name:周润发
    2♥ A♠ A♣ K♣ Q♠ Q♥ J♥ J♣ J♦ 10♠ 10♥ 9♠ 8♦ 7♣ 6♠ 6♥ 4♦ 
    name:周星驰
    小王 2♠ 2♣ K♠ Q♣ 10♣ 9♣ 8♠ 8♣ 6♣ 5♥ 5♣ 4♠ 4♣ 3♠ 3♥ 3♣ 
    name:底牌
    大王 A♥ 5♠ 
发布了42 篇原创文章 · 获赞 6 · 访问量 1135

猜你喜欢

转载自blog.csdn.net/qq_40572023/article/details/104619722
今日推荐