黑马程序员技术交流社区

标题: [石家庄校区]就业班JavaSE高级部分day04 Map [打印本页]

作者: 湿漉漉的文字控    时间: 2018-11-20 15:49
标题: [石家庄校区]就业班JavaSE高级部分day04 Map
就业班JavaSE高级部分day04 Map
Map集合:(java.util.Map)
1.Map集合是一个双列集合,一个元素包含两个值(一个key, 一个value)
2.两个值的类型可以相同,可以不同
3.key不允许重复,value可以重复
4.key和value是一一对应的,一个键对应一个值
HashMap集合(implements Map<K, V>接口)
1.底层是哈希表,查询速度快
2.是一个无序的集合,存取元素的顺序可能不一致
LinkedHashMap集合:(implements Map<K, V>接口)
1.底层是哈希表+链表
2.是一个有序集合,存取元素的顺序一致
Map方法:
java.util.Map接口: 双列集合的顶层
        // 成员方法
        V put(K key, V value): 添加/修改 键值对.
            如果键存在, 则用新值替换已有值, 返回被替换的值; 如果键不存在, 添加键值对, 返回null
        V remove(Object key): 根据键删除键值对, 返回被删除元素的值
                如果键不存在, 返回null
        V get(Object key): 根据键获取值.
            如果键不存在, 则返回null
        boolean containsKey(Object key): 判断是否包含指定的键

        Set<K> keySet(): 获取Map集合中所有的键, 存储到Set集合中
        Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的Entry对象的集合(Set集合)
Map遍历方式一: keySet()方法实现通过键找值:
Set<K> keySet(): 获取Map集合中所有的键, 存储到Set集合中
       
keySet()遍历步骤:
        1. Map对象调用 keySet() 方法, 获取包含所有key的Set集合
        2. 遍历Set集合, 获取每个key
        3. 通过Map对象调用 get(Object key) 方法根据key获取到value
       
        Map<String, String> map = new HashMap<>();
        // keySet()遍历
        Set<String> keys = map.keySet();
        for (String key : keys) {
                // 通过每个键获取值
                String value = map.get(key);
                // 打印当前键值对
                System.out.println(key + "=" + value);
        }
Map遍历方式二: Entry键值对对象
java.util.Map.Entry接口:
        // 常用成员方法
        K getKey(): 获取Entry对象中的键
        V getValue(): 获取Entry对象中的值
Entry对象就是一个节点, 节点中存储了key和value
拿到一个Entry对象就可以从中获取key和value
        // HashMap中Entry实现类
        static class Node<K,V> implements Map.Entry<K,V> {
            final int hash;
            final K key;
            V value;
            Node<K,V> next;
            public final K getKey() {
                return key;
            }
            public final V getValue() {
                return value;
            }
        }
entrySet()获取Entry对象形式遍历
java.util.Map接口
        Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)
java.util.Map接口
        Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)
entrySet()方法遍历Map步骤:
        1. Map对象调用 entrySet() 获取包含所有Entry对象的Set集合
        2. 遍历Set集合, 获取每个Entry对象
        3. 调用Entry对象的 getKey() 和 getValue() 方法获取键和值
        Map<String, String> map = new HashMap<>();
        // keySet()遍历
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            // 通过Entry对象获取每个键值对
            String value = entry.getKey();
            String value = entry.getValue();
            // 打印当前键值对
            System.out.println(key + "=" + value);
HashMap存储自定义数据类型作为键
HashMap存储自定义JavaBean对象作为key保证key唯一不重复, 需要让JavaBean重写 hashCode() 和 equals() 方法
LinkedHashMap类
LinkedHashMap底层: 哈希表 + 链表
key不允许重复, 但key存取有序
Hashtable类
Hashtable和HashMap:
        相同点:
                1. 底层都是哈希表
        不同点:
                1. Hashtable不允许存储 null 值和 null 键; HashMap允许存储 null 值和 null 键
                2. Hashtable线程安全效率低; HashMap线程不安全效率高               
Hashtable目前很少使用.
但其子类 Properties 集合, 可以与IO流结合使用, 应用较多
Map案例
public class Test {
    public static void main(String[] args) {
        // 键盘录入
        Scanner scanner = new Scanner(System.in);
        String s = scanner.next();
        // 创建Map集合
//        Map<Character, Integer> map = new HashMap<>();
        Map<Character, Integer> map = new TreeMap<>(); // TreeMap
        // 将字符串转换为char[]
        char[] arr = s.toCharArray();
        // 遍历字符数组中的字符
        for (char c : arr) {
            // 先判断该字符是否在map中存储过
            if (map.containsKey(c)) {
                // 包含该key, 则需要取出value的次数, 增加1, 再存回去
                Integer count = map.get(c);
                count++;
                map.put(c, count);
            } else {
                // 不包含该key, 则认为是第一次遇到, 次数为1次
                map.put(c, 1);
            }
        }
        // 遍历map查看
        for (Map.Entry<Character, Integer> entry : map.entrySet()) {
            Character ch = entry.getKey();
            Integer count = entry.getValue();
            System.out.println(ch + "=" + count);
        }
    }
}
JDK9对添加的优化
1. of() 方法只适用于List接口, Set接口, Map接口, 不适用于接口的实现类
        2. of() 方法的返回值是一个不可变的集合, 集合不能再使用 add(), put() 方法添加元素, 会抛出异常
        3. Set接口和Map接口在调用 of() 方法的时候, 不能有重复的元素, 否则会抛出异常
Debug调试模式
断点:
        breakpoint, 在debug模式下, 程序运行到断点会暂停住, 便于我们在程序运行过程中查看
Debug调试程序:
    可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
使用方式:
    在行号的右边,鼠标左键单击,添加断点(每个方法的第一行,哪里有bug添加到哪里)
    右键,选择Debug执行程序
    程序就会停留在添加的第一个断点处
执行程序:
    f8:逐行执行程序
    f7:进入到方法中
    shift+f8:跳出方法
    f9:跳到下一个断点,如果没有下一个断点,那么就结束程序
    ctrl+f2:退出debug模式,停止程序
    Console:切换到控制台
斗地主发牌案例
分析:
准备牌:
                为了牌有大小顺序, 给牌编号, 一个编号对应一张牌: 0=大王, 1=小王, 2=♤2, 3=♤3 ...
                编号和牌是一对一映射关系, 用HashMap<Integer, String>存储, key为编号, value为牌
                再为编号单独创建一个额外的ArrayList<Integer> pokerIndex
                定义编号变量 int index = 0;
                按照编号添加大小王
                嵌套for循环拼接序号和花色, 存入HashMap, 同时将编号存入ArrayList, 编号index++
        洗牌:
                Collections.shuffle(List list)将编号的ArrayList pokerIndex打乱顺序
        发牌:
                创建4个ArrayList, 前3个是玩家, 最后一个是底牌
                遍历编号的ArrayList pokerIndex, 发编号给玩家, >=51时发给底牌
                对4个ArrayList排序
        看牌
                定义方法:
                public static void lookPoker(String name, HashMap<Integer, String> poker, ArrayList<Integer> list)
                        方法内打印姓名, 遍历编号集合ArrayList<Integer> list获取每个编号, 通过编号从HashMap<Integer,String> poker中获取牌, 打印
                调用方法传入 玩家姓名, 牌的Map集合, 玩家集合 来看牌
代码
public class Test {
    public static void main(String[] args) {
        /*
            准备牌
         */
        // 定义花色和数值集合
        List<String> colors = List.of("♤", "♡", "♣", "♢");
        List<String> numbers = List.of("2", "A", "K", "Q", "J", "10", "9", "8", "7", "6", "5", "4", "3");
        // 定义牌盒map
        HashMap<Integer, String> poker = new HashMap<>();
        // 定义牌的序号集合list
        ArrayList<Integer> pokerIndex = new ArrayList<>();

        // 定义一个索引作为牌的序号
        int index = 0;
        // 先添加大小王
        poker.put(index, "大王");
        pokerIndex.add(index);
        index++;
        poker.put(index, "大王");
        pokerIndex.add(index);
        index++;

        // 然后拼接牌, 并添加
        for (String number : numbers) {
            for (String color : colors) {
                String pai = color + number;
                // 添加到牌盒
                poker.put(index, pai);
                // 添加索引
                pokerIndex.add(index);
                // 增加索引
                index++;
            }
        }

        /*
            洗牌
         */
        Collections.shuffle(pokerIndex);

        /*
            发牌
         */
        // 创建玩家和底牌集合, 存储序号
        ArrayList<Integer> player01 = new ArrayList<>();
        ArrayList<Integer> player02 = new ArrayList<>();
        ArrayList<Integer> player03 = new ArrayList<>();
        ArrayList<Integer> diPai = new ArrayList<>();
        // 遍历序号集合, 发序号
        for (int i = 0; i < pokerIndex.size(); i++) {
            //取出一个序号
            Integer in = pokerIndex.get(i);
            // 发
            if (i >= 51) {
                diPai.add(in);
            } else if (i % 3 == 0) {
                player01.add(in);
            } else if (i % 3 == 1) {
                player02.add(in);
            } else if (i % 3 == 2) {
                player03.add(in);
            }
        }

        /*
            排序
         */
        Collections.sort(player01);
        Collections.sort(player02);
        Collections.sort(player03);
        Collections.sort(diPai);
        
        /*
            看牌
         */
        lookPoker("刘备", poker, player01);
        lookPoker("关羽", poker, player02);
        lookPoker("张飞", poker, player03);
        lookPoker("底牌", poker, diPai);
    }

    // 定义一个方法来看牌
    private static void lookPoker(String name, HashMap<Integer, String> poker, ArrayList<Integer> list) {
        // 先打印玩家名称
        System.out.print(name + ":");
        // 然后遍历序号集合, 通过序号获取map中的牌
        for (Integer key : list) {
            String pai = poker.get(key);
            // 打印牌
            System.out.print(pai + " ");
        }
        // 打印完一个玩家的牌后换行
        System.out.println();
    }
}






欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2