Java进阶学习4:【Map集合、keySet遍历、entrySet遍历、Debug调试】

  • A+
所属分类:Java Java进阶

01. Map集合的介绍

Map是一个双列集合,里面的每一个元素都是一个键值对。

键不能重复,值允许重复

我们可以根据键的值找到value的值。

02. Map中的常见方法

/*
    Map是一个双列集合,里面的每一个元素都是由键值对组成的。
    Map<K,V>有两个泛型, K表示键的数据类型, V表示值的数据类型。

    常用方法:
        (常用)V put(K key, V value): 将键和值添加到Map集合中。如果该键已经存在,那么会使用新的值覆盖掉原来的值。
        (常用)V get(Object key): 根据键获取对应的值。
        V remove(Object key): 根据键删除整个的键值对。

    Map是一个接口,如果要用,需要使用实现类,最常用的实现类是HashMap
 */
public class Demo01MapMethod {
    public static void main(String[] args) {
        //定义一个Map集合,key是整数, value是字符串
        Map<Integer, String> map = new HashMap<>();
        //向Map集合中添加元素
        map.put(100, "刘德华");
        map.put(200, "张学友");
        map.put(300, "黎明");
        //输出map集合
        System.out.println("map:" + map);
        //V get(Object key): 根据键获取对应的值。
        System.out.println(map.get(100)); //刘德华
        System.out.println(map.get(300)); //黎明
        System.out.println(map.get(10000)); //null  如果该键在集合中不存在,那么返回null值。
        //V remove(Object key): 根据键删除整个的键值对。返回值为被删除的值
        String value = map.remove(200);
        System.out.println("map:" + map);
        System.out.println("value:" + value);

        System.out.println("======================");

        //定义Map集合,key和value都是字符串
        Map<String, String> map2 = new HashMap<>();
        //添加元素
        map2.put("it001", "柳岩");
        map2.put("it002", "大幂幂");
        map2.put("it003", "金星");
        //如果调用put方法添加元素时该键已经存在,那么就会使用新的值覆盖掉原来的值。
        //map2.put("it002", "王思聪");
        System.out.println("map2:" + map2);

        //如果调用put方法没有覆盖掉任何元素,那么put方法返回的结果是null。
        System.out.println(map2.put("it004", "李小璐")); //null
        //如果调用put方法产生了覆盖效果,那么put方法返回值为被覆盖掉的值。
        System.out.println(map2.put("it004", "白百合")); //李小璐
    }
}

03. keySet遍历

/*
    Map集合不能直接使用增强for或者迭代器去遍历。
    如果要遍历Map集合,那么我们可以先拿到Map集合中的所有的key, 把所有的key放入到一个Set集合, 遍历    这个Set集合
    拿到里面的每一个key,根据key获取对应的value。

    如何拿到Map集合中的所有的key? 使用Map集合的keySet方法即可
        Set<K> keySet(): 获取所有的键,并把所有的键放入到Set集合中返回

    遍历步骤:
        1. 调用Map集合的keySet方法,获取到所有的key,并放入到一个Set集合中返回。
        2. 遍历Set集合, 拿到里面的每一个键。
        3. 调用Map的get方法,根据获取到的键得到对应的值。
 */
public class Demo02KeySet {
    public static void main(String[] args) {
        //定义一个Map集合
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("it001", "张三");
        map.put("it002", "李四");
        map.put("it003", "王叔叔");
        //遍历Map集合。
        //1. 调用Map集合的keySet方法,获取到所有的key,并放入到一个Set集合中返回。
        Set<String> set = map.keySet();
        //2. 遍历Set集合, 拿到里面的每一个键。
        for (String key : set) {
            //3. 调用Map的get方法,根据获取到的键得到对应的值。
            String value = map.get(key);
            System.out.println(key + "-" + value);
        }
    }
}

05. Map集合的entrySet遍历

/*
    Map集合的另外一种遍历方式是获取到Map集合中的所有的Entry对象然后再进行遍历。

    Map集合中获取Entry对象的方法:
        Set<Map.Entry<K,V>> entrySet(): 获取所有的Entry对象并放入到Set集合中返回。

    Entry中,获取键和值的方法:
        K getKey(): 获取Entry对象中的键
        V getValue(): 获取Entry对象中的值。

     Map集合的entrySet遍历步骤:
        1. 使用Map集合调用entrySet方法获取所有的entry对象,并放入到Set集合中
        2. 遍历Set集合,拿到里面的每个Entry对象。
        3. 通过遍历到的Entry对象获取键和值。

    遍历Map集合有两种方式
        1. 使用keySet的方式遍历。(推荐)
        2. 使用entrySet的方式遍历。

 */
public class Demo03EntrySet {
    public static void main(String[] args) {
        //定义一个集合
        Map<String, String> map = new HashMap<>();
        //添加元素
        map.put("it001", "小苍");
        map.put("it002", "小泽");
        map.put("it003", "小波");
        //使用entrySet的方式遍历集合
        //1. 使用Map集合调用entrySet方法获取所有的entry对象,并放入到Set集合中
        Set<Map.Entry<String, String>> set = map.entrySet();
        //2. 遍历Set集合,拿到里面的每个Entry对象。
        for (Map.Entry<String, String> entry : set) {
            //3. 通过遍历到的Entry对象获取键和值。
            String key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "-----" + value);
        }
    }
}

06. HashMap保证唯一性的方式

/*
    练习: 定义Map集合,key为学生对象(属性有姓名和年龄), value是家庭住址。
          并且保证唯一性(学生姓名相同和年龄相同,那么就看成是同一个学生)

    HashMap中的key判断唯一性的方式和HashSet一模一样, 原因是因为HashSet内部是在使用HashMap保存数据,所以他俩本质相同。
    1. 先比较两个对象的哈希值。
        如果哈希值不同,肯定是不同的对象。
        如果哈希值相同,那么不一定是同一个对象。
    2. 如果哈希值相同,还需要使用equals进行比较。
        如果equals结果是true,表示两个对象相同,
        如果equals结果是false,表示两个对象不同。

    如果要保证HashMap中的key的唯一性,需要重写对应的hashCode和equals。

 */
public class Demo04MapTest {
    public static void main(String[] args) {
        //定义一个Map集合,key是Student类型, value是家庭住址
        Map<Student, String> map = new HashMap<>();
        //向Map集合中添加元素
        map.put(new Student("杨过", 20), "终南山");
        map.put(new Student("小龙女", 22), "古墓");
        map.put(new Student("尹志平", 25), "全真教");

        map.put(new Student("小龙女", 22), "东海龙宫");

        //遍历Map集合,输出里面的每一个键值对
        //拿到所有的key,并到Set集合返回
        Set<Student> set = map.keySet();
        //遍历存放所有key的集合, 拿到里面的每一个键
        for (Student key : set) {
            //通过map调用get方法,根据键获取对应的值
            String value = map.get(key);
            System.out.println(key + "=========" + value);
        }
    }
}

public class Student {
    private String name;
    private int age;

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;

        Student student = (Student) o;

        if (age != student.age) return false;
        return name != null ? name.equals(student.name) : student.name == null;
    }

    @Override
    public int hashCode() {
        int result = name != null ? name.hashCode() : 0;
        result = 31 * result + age;
        return result;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", age=" + age +
                '}';
    }

    public Student() {
    }

    public Student(String name, int age) {

        this.name = name;
        this.age = age;
    }

    public String getName() {

        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

07. LinkedHashMap的特点

/*
    LinkedHashMap是Map接口下面的另一个实现类。
    LinkedHashMap里面除了有一个哈希表之外,还有一个链表,可以保证有序
 */
public class Demo05LinkedHashMap {
    public static void main(String[] args) {
        //定义Map集合
        Map<String, String> map = new LinkedHashMap<>();
        //添加元素
        map.put("it001", "小明");
        map.put("it002", "小强");
        map.put("it003", "小红");
        //输出集合
        System.out.println(map);
    }
}

08. Map集合的练习

/*
    练习: 统计字符串中每个字符有多少个

    思路:
        1. 键盘录入一个字符串。
        2. 定义一个Map集合当做计数器, key是字符, value是该字符出现的次数。
        3. 遍历字符串,拿到字符串中的每个字符
        4. 判断拿到的字符之前有没有统计过(判断Map集合中的key是否包含该字符)
               如果之前统计过, 将对应的次数加1.
               如果之前没有统计过, 将这个字符添加到Map集合中, 并且把对应的value设置为1
 */
public class Demo06MapTest {
    public static void main(String[] args) {
        //键盘录入一个字符串。
        Scanner sc = new Scanner(System.in);
        System.out.println("请您键盘录入一个字符串");
        String str = sc.nextLine();
        //定义一个Map集合当做计数器, key是字符, value是该字符出现的次数。
        Map<Character, Integer> map = new HashMap<>();
        //遍历字符串,拿到字符串中的每个字符
        for(int i = 0; i < str.length(); i++) {
            //变量c表示的就是每一个字符
            char c = str.charAt(i);

            //判断拿到的字符之前有没有统计过(判断Map集合中的key是否包含该字符)
            //如果map集合中的key包含该字符,就说明之前统计过
            if(map.containsKey(c)) { //判断map集合中的key是否包含当前遍历到的字符
                //如果之前统计过, 将对应的次数加1
                map.put(c, map.get(c) + 1);
            } else {
                //否则表示没有统计过。
                //如果之前没有统计过, 将这个字符添加到Map集合中, 并且把对应的value设置为1
                map.put(c, 1);
            }


            //扩展写法,三元运算符
            //map.put(c, map.containsKey(c) ? map.get(c) + 1 : 1);
        }

        //遍历打印map集合
        Set<Character> set = map.keySet();
        //遍历保存所有键的set集合
        for(Character key : set) {
            System.out.println(key + ":" + map.get(key));
        }

    }
}

09. 可变参数的使用

/*
    在JDK5的时候,多了一个新特性叫做可变参数。

    可变参数就是方法参数的数量可以变化。

    定义格式:
        修饰符 返回值类型 方法名(参数类型... 参数名) {
            方法体;
        }
        1. 如果调用带有可变参数的方法,可以在可变参数位置传递任意个参数。
        2. 传递的参数必须是同一个数据类型。
        3. 可变参数本质是数组, 数组怎么用,可变参数就怎么用。
        4. 可变参数本质是数组, 所以也可以向可变参数位置传递一个数组。

    可变参数的注意事项
        1. 一个方法中最多只能有一个可变参数。
        2. 可变参数只能放在方法的最后一个位置
 */
public class Demo01Params {
    public static void main(String[] args) {
        //int sum = getSum(1,2,3);

        //System.out.println("sum:" + sum);

        int[] arr = {1,2,3};
        int sum = getSum(arr);
        System.out.println(sum);
    }

    /*
        定义方法,求任意整数的和(使用可变参数)
     */
    public static int getSum(int... nums) {
        //对nums中的所有元素求和。 nums本质是一个数组,可以把它当成数组去用
        int sum = 0;
        for (int num : nums) {
            sum += num;
        }
        return sum;
    }

    /*
        定义方法,求任意个整数的和。
     */
    /*
    public static int getSum(int[] arr) {
        //定义变量,用来记录累加和
        int sum = 0;
        //遍历数组,将里面的每一个元素累加到sum上
        for (int num : arr) {
            sum += num;
        }
        return sum;
    }
    */
}

10. Collections中的addAll方法

/*
    在Collections中,有一个方法叫做addAll,作用是可以批量添加元素
        static boolean addAll(Collection c, T... elements):批量添加元素
            参数c:表示要向哪个集合中添加元素
            参数elements: 表示向集合中添加哪些元素。 该参数是一个可变参,所以可以传递任意个参数。
 */
public class Demo02Collections {
    public static void main(String[] args) {
        //定义集合
        ArrayList<String> list = new ArrayList<>();
        //添加元素
        //list.add("你好");
        //list.add("我好");
        //list.add("大家好好");

        //调用collections的静态方法addAll批量添加元素
        Collections.addAll(list, "你好", "我好", "大家好");

        System.out.println("list:" + list);
    }
}

11. Debug调试的基本使用

/*
    bug: 本意是小虫子。 在计算机的世界中bug指的是出现了问题。
    debug: 解决bug。

    debug调试也叫作断点调试。

    断点: 可以让程序在运行的过程中停下来。
    如何加: 我们需要在某行代码的左边区域单击, 将来运行程序,程序就可以在这一行停下来。如果要取消断点,再点击一次。
    如何运行: 右键->Debug...

    F8: 让代码向下执行一行
    F9: 释放断点, 让代码一直往下执行。
    ctrl + F2: 强制停止程序

    Debug调试: 可以查看程序的执行流程。
 */
public class Demo01Debug {
    public static void main(String[] args) {
        int a = 10;
        int b = 20;
        int sum = a + b;
        System.out.println("sum:" + sum);
    }
}

12. Debug查看方法执行流程

/*
    debug查看方法的执行流程
        1. 如果要进入到某个方法,那么我们可以在这个方法中也加上断点(推荐)
        2. 我们可以使用另一个快捷键(F7),这个快捷键可以进入到方法
 */
public class Demo02Debug {
    public static void main(String[] args) {
        System.out.println("main开始了");
        int sum = getSum(1, 2);
        System.out.println("sum:" + sum);
    }

    /*
        定义方法,求两个整数的和
     */
    public static int getSum(int a, int b) {
        int sum = a + b;
        return sum;
    }
}

13. 斗地主案例

/*
    斗地主的步骤
        1. 准备牌
        2. 洗牌
        3. 发牌
        4. 看牌
 */
@SuppressWarnings("all") //抑制警告
public class Demo01Game {
    public static void main(String[] args) {
        //1. 准备牌
        //定义List集合,保存牌的编号
        List<Integer> poker = new ArrayList<>();
        //定义Map集合,保存编号和牌的对应关系。 key为编号,value为具体的扑克牌
        Map<Integer, String> map = new HashMap<>();
        //向List集合中添加编号,向map集合中添加对应关系
        //定义变量,表示编号
        int index = 0;
        //定义数组,保存所有的花色
        String[] colors = {"♠", "♥", "♣", "♦"};
        //定义数组,保存所有的点数
        String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        //遍历两个数组,对花色和点数进行组合
        for(String num : nums) {
            for(String color : colors) {
                //添加编号
                poker.add(index);
                //添加对应关系
                map.put(index, color + num);
                //把编号自增
                index++;
            }
        }
        //添加小王
        poker.add(index);//编号
        map.put(index, "小王");//对应关系
        index++;
        //添加大王
        poker.add(index);//编号
        map.put(index, "大王");//对应关系

        //2. 洗牌
        //洗牌操作真正操作的是编号。
        //使用Collections的shuffle打乱顺序
        Collections.shuffle(poker);

        //3. 发牌
        //定义三个集合,保存每个玩家手里的牌(真正保存的是牌的编号)
        List<Integer> playerOne = new ArrayList<>();
        List<Integer> playerTwo = new ArrayList<>();
        List<Integer> playerThree = new ArrayList<>();
        //定义集合,保存底牌(真正保存的是牌的编号)
        List<Integer> diPai = new ArrayList<>();
        //遍历集合,拿到集合中的每一张牌。 根据这张牌的索引进行发牌。
        for (int i = 0; i < poker.size(); i++) {
            //获取到当前遍历到的扑克牌(真正获取的是扑克牌对应的编号)
            Integer card = poker.get(i);
            //给玩家发牌之前处理底牌, 如果获取到的是倒数三张牌,那么就放入到底牌的集合中
            if(i >= 51) {
                //如果条件成立,那么表示不足三张牌,那么就添加到底牌集合
                diPai.add(card);
                continue;//结束本次循环,继续开始下次循环。
            }

            //根据牌在集合中的索引进行发牌。
            if(i % 3 == 0) { //如果牌的索引是0,3,6...(索引对3取余结果是0的),那么就发给第一个玩家
                playerOne.add(card);
            } else if(i % 3 == 1) { //如果索引对3取余结果是1,那么就发给第二个玩家
                playerTwo.add(card);
            } else {
                //否则索引对3取余结果肯定是2,那么就发给第三个元素
                playerThree.add(card);
            }
        }

        //4. 看牌
        lookCard("周星驰", playerOne, map);
        lookCard("周润发", playerTwo, map);
        lookCard("刘德华", playerThree, map);

        lookCard("底牌", diPai, map);
    }
    /*
        定义方法实现看牌
            参数: 玩家姓名, 玩家手里的牌(真正保存的编号), 保存对应关系的Map集合。

            步骤:
                1. 先对玩家手中的编号进行排序。
                2. 根据编号找到对应的牌,进行输出。
     */
    public static void lookCard(String name, List<Integer> list, Map<Integer, String> map) {
        //打印姓名
        System.out.print(name + ": ");
        //先对玩家手中的编号进行排序。
        Collections.sort(list);
        //根据编号找到对应的牌,进行输出。
        //遍历玩家手中的编号的集合,拿到里面的每个编号,去Map集合中查询这个编号对应的牌。
        for (Integer id : list) {
            //根据编号找到牌
            String card = map.get(id);
            //输出
            System.out.print(card + " ");
        }
        //输出空换行
        System.out.println();
    }
}
  • 资源分享QQ群
  • weinxin
  • 官方微信公众号
  • weinxin
沙海
网站https安全证书安装,伪静态配置
美女讲师教你学C语言
C语言项目源码分享
Linux服务器网站环境安装

发表评论

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen: