Java学习 第二十四章 Map集合 /JDK9对集合添加的优化/模拟斗地主洗牌发牌

第二十四章

一、 接口Map<K,V>

1.1 Map集合概述

将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。
Map中的集合称为双列集合 键是唯一的,值可以重复

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

在这里插入图片描述

1.2 Map常用子类

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

 java.util.LinkedHaspMap的特点:
    1.LinkedHaspMap的集合底层是哈希表 + 链表(保证迭代的顺序)
    2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

1.3 Map接口中常用的方法

java.util.Map<k,v>集合
Map集合的特点:

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

HashMap集合的特点:

    1.HashMap集合底层是哈希表。查询的速度特别的快
     JDK1.8之前:数组 +单向链表
     JDK1.8之后:数组 + 单向链表/红黑树(链表的长度超过8)
    2.HashMap集合是一个无序集合,存储元素和取出元素的顺序有可能不一致

java.util.LinkedHaspMap的特点:

    1.LinkedHaspMap的集合底层是哈希表 + 链表(保证迭代的顺序)
    2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

public class Demo01Map {
    public static void main(String[] args) {
        //show01();
        //show02();
        //show03();
        show04();
    }
      /*
        boolean containsKey(Object key)判断集合中是否包含指定的键
            包含返回true,不包含返回false

     */

    private static void show04() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        boolean b1 = map.containsKey("赵丽颖");
        System.out.println("b1 = " + b1);//true

        boolean b2 = map.containsKey("赵颖");
        System.out.println("b2 = " + b2);//true

    }

    /*
        public V get(Object key)根据指定的键,在Map集合中获取对应的值
        返回值:v
                    key存在,v返回对应的值
                    key不存在,v返回null

     */
    private static void show03() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        Integer v1  = map.get("杨颖");
        System.out.println("v1 = " + v1);//key存在,v返回对应的值v1 = 165

        Integer v2 = map.get("迪丽热巴");
        System.out.println("v2 = " + v2);//null key不存在,v返回null


    }

    /*

    public V put(K key , V value):把指定的键所对应的的值,从Map集合中删除,返回被删除元素的值
            返回值:v
                key存在,v返回被删除的值
                key不存在,v返回null
   */
    private static void show02() {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);
        System.out.println(map);//{林志玲=178, 赵丽颖=168, 杨颖=165}

        Integer v1 = map.remove("林志玲");
        System.out.println("v1 = " + v1);//v1 = 178
        System.out.println(map);//{赵丽颖=168, 杨颖=165}

        Integer v2 = map.remove("林志颖");//没有对应的值
        System.out.println("v2 = " + v2);//v2 = null
        


    }

    /*
        public V put(K key , V value):把指定的键与指定的值添加到Map集合中
        返回值:v
                存储键值对的时候,key不重复,返回值V是null
                                key重复,会使用新的value值替换map中重复的value,返回被替换的value
     */
    private static void show01() {
        //创建Map集合对象,多态
        Map<String,String> map = new HashMap<>();

       String v1= map.put("张三","李四1");
        System.out.println("v1 = " + v1 );//v1 = null

        String v2= map.put("张三","李四2");
        System.out.println("v2 = " + v2 );//v2 = 李四1 返回被替换的值

        System.out.println(map);//{张三=李四2}

        map.put("A","a");
        map.put("B","b");
        map.put("C","b");
        System.out.println(map);

    }

}

1.4 Map集合遍历键找值方式

Map集合的第一种遍历方式,通过键找值的方式:

 Map集合中的方法:
            Set<K> keySet() :返回此映射中包含的键的 Set 视图。
 实现步骤:
        1.使用Map集合中的方法KeySet(),把Map集合中所有的key取出来,存储到一个Set集合中去
        2.遍历set集合,获取Map集合中的每一个key
        3.通过Map集合中的方法get(key),通过key找到value

在这里插入图片描述

public class Demo02KeySet {
    public static void main(String[] args) {
        Map<String,Integer> map = new HashMap<>();

        map.put("A",1);
        map.put("B",2);
        map.put("C",3);

       // 1.使用Map集合中的方法KeySet(),把Map集合中所有的key取出来,存储到一个Set集合中去
        Set<String> set = map.keySet();
        //使用迭代器遍历set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key + "="+value);

        }
        System.out.println("-----------");
        //使用增强for循环遍历set集合
        for (String key : set) {
            Integer value = map.get(key);
            System.out.println(key + "="+value);

        }
        //使用增强for循环遍历set集合,优化 将set替换为map.keySet //Set<String> set = map.keySet();
        for (String key : map.keySet()) {
            Integer value = map.get(key);
            System.out.println(key + "="+value);

        }





    }



}

1.5 Map键值对对象

嵌套类摘要
static interface Map.Entry<K,V>
映射项(键-值对)。
在这里插入图片描述

1.6 Map集合遍历键值对方式

Map集合遍历的第二种方式:使用Entry对象遍历

Map集合中的方法:
            Set<Map.Entry<K,V>> entrySet()返回此映射设中包含的映射关系的Set视图
实现步骤:
        1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        2.遍历Set集合,获取每一个Entry对象
        3.使用Entry对象中的方法getKey()和getValue()获取键与值

public class Demo03EntrySet {
    public static void main(String[] args) {
        //创建Map集合对象
        Map<String,Integer> map = new HashMap<>();

        map.put("A",1);
        map.put("B",2);
        map.put("C",3);

       // 1.使用Map集合中的方法entrySet(),把Map集合中多个Entry对象取出来,存储到一个Set集合中
        Set<Map.Entry<String,Integer>> set = map.entrySet();

        //   2.遍历Set集合,获取每一个Entry对象
        //使用迭代器遍历每一个循环
        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循环
                for (Map.Entry<String, Integer> m : set) {
                String key1 = m.getKey();
                Integer value1 = m.getValue();
                System.out.println(key1 + "=" + value1);

            }

    }
}

1.6 HashMap集合存储自定义键值类型

/*
    HashMap存储自定义类型的键值
    Map集合保证key是唯一的:
        作为key的元素,必须重写hasCode方法和equals方法,以保证key唯一
 */
public class Demo01HashMapSavePerson {
    public static void main(String[] args) {
      //  show01();
        show02();

    }
/*
    HaspMap存储自定义键值
        key:Person类型
                因为key必须是唯一的,所以Person类就必须重写hashCode和equals方法
        value:String类型
                value可以重复

 */
    private static void show02() {
        //创建HashMap对象
        HashMap<Person,String> map = new HashMap<>();
        //存储数据
        map.put(new Person("张三",18),"北京");
        map.put(new Person("李四",19),"上海");
        map.put(new Person("王五",20),"北京");
        map.put(new Person("张三",18),"北京");//不重写hashCode和equals方法,会出现相同数据


        //一、使用map中的keySet方法获取键值
        Set<Person>  set = map.keySet();
        //创建迭代器遍历
        Iterator<Person> it = set.iterator();
        while (it.hasNext()){
            Person key = it.next();
            String value = map.get(key);
            System.out.println(key+"="+value);

        }
        System.out.println("--------------");
        //二、使用Map的 entrySet和增强for遍历HashMap集合
        Set<Map.Entry<Person,String>> set1 = map.entrySet();
        for (Map.Entry<Person, String> entry : set1) {
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key +"=" + value);



        }



    }

    /*
            HashMap存储自定义类型键值
            key:String类型
                String类重写hashCode方法和equals方法,可以保证key唯一
            value:Person类型
                value可以重复(同名同年龄的人视为同一个)

     */
    private static void show01() {
        //创建HashMap集合
        HashMap<String , Person> map = new HashMap<>();

        //往集合中添加元素
        map.put("北京",new Person("张三",18));
        map.put("上海",new Person("李四",19));
        map.put("广州",new Person("王五",20));
        map.put("北京",new Person("赵六",18));//键值不允许重复。会替换张三

        //一、使用Map集合中的keySet(),把Map集合中的所有key取出来
        Set<String> set = map.keySet();
        //使用迭代器遍历set
        Iterator<String> it = set.iterator();
        while(it.hasNext()){
            String s = it.next();//获取键值
            //通过Map集合中的方法get(key),通过key找到value
            Person p = map.get(s);
            System.out.println(s+"="+p);

        }
        System.out.println("----------");

        //二、使用Map的 entrySet遍历HashMap集合
        Set<Map.Entry<String, Person>> set1 = map.entrySet();
        for (Map.Entry<String, Person> entry : set1) {
            String key = entry.getKey();
            Person value = entry.getValue();
            System.out.println(key +"="+ value);


        }



    }

}

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

    public Person(String name, int age) {
        this.name = name;
        this.age = age;
    }

    public Person() {
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, 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;
    }
}

1.6 LinkedHashMap集合

/*
    java.util.LinkedHashMap<K,V>  extends HashMap
                Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。
           底层原理:
                    哈希表+链表(记录元素顺序)
 */
public class Demo02LinkedHashMap {
    public static void main(String[] args) {
        HashMap<String,String> map = new HashMap<>();

        map.put("a","a");
        map.put("c","c");
        map.put("b","b");
        map.put("d","d");
        System.out.println(map);//key不允许重复 ,无序的集合{a=a, b=b, c=c, d=d}

        LinkedHashMap<String,String> map1 = new LinkedHashMap<>();

        map1.put("a","a");
        map1.put("c","c");
        map1.put("b","b");
        map1.put("d","d");
        System.out.println(map1);//key不允许重复 ,有序的集合{a=a, c=c, b=b, d=d}
        
        
    }
}

1.6 Hashtable集合

/*
    java.util.Hashtable<K,V> 集合 implements Map<K,V>接口
        Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
        HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合速度快

        HashMap(之前学的所有集合都可以)集合可以存储null值,null键
        Hashtable:不能存储null值,null键

        Hashtable 和vector集合一样,在jdk1.2版本之后被更先进的集合(HashMap,ArrayList)取代了
         Hashtable的子类Properties依然常用

         Properties集合是唯一一个和IO流相结合的集合

* /
public class Demo03HashTable {
    public static void main(String[] args) {
        HashMap<String ,String> map = new HashMap<>();

        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("b",null);//NullPointerException 空指针异常,不能存储null
      //  table.put(null,"b");//NullPointerException 空指针异常,不能存储null
       // table.put(null,null);//NullPointerException 空指针异常,不能存储null


    }
}

1.7 Map集合练习

计算一个字符串中,每个字符出现的次数
在这里插入图片描述

/*
    1.使用Scanner获取一个字符串对象。
    2.创建Map集合,key是字符串中的字符,value是字符的个数
    3.遍历字符串,获取每一个字符
    4.使用获取到的字符,去Map集合判断key是否存在
       key存在:
            通过字符(key)获取value(字符个数)
            value++
            put(key,Value)吧新的value存储到Map集合中
       key不存在:
            put(key,1)
      5.遍历Map集合,输出结果。
 */
public class Demo04 {
    public static void main(String[] args) {
        System.out.println("请输入一个字符串");
        //1获取键盘输入的字符串
        Scanner sc = new Scanner(System.in);
        String s = sc.next();
        char[] chars = s.toCharArray();
        //2.创建一个HashMap对象,
        HashMap<Character , Integer> map = new HashMap<>();
        //使用增强for遍历字符串
        for (char c: s.toCharArray()) {
            //4.使用获取到的字符,去Map集合判断key是否存在
            boolean b = map.containsKey(c);
            if(b == true){
                //key存在
                Integer value = map.get(c);
                value++;
                map.put(c,value);
            }else {
               // key不存在
                map.put(c,1);
            }
        }
        //5.遍历输出HashMap map.entrySet  使用Entry对象中的方法getKey()和getValue()获取键与值
        Set<Map.Entry<Character,Integer>> set =  map.entrySet();
        for (Map.Entry<Character, Integer> entry : set) {
            Character key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(entry +"="+value);

        }

        System.out.println("-------------");
        //或者用keySet遍历 ,
        Set<Character> set1 = map.keySet();
        for (Character key:set1
             ) {
            Integer value = map.get(key);
            System.out.println(key + "=" +value);
        }


    }
}

二、JDK9对集合添加的优化

2.1 给集合一次性添加多个元素


/*
    JDK9的新特性:
        List接口,Set接口,Map接口:里边增加了一个静态的方法of,可以给集合一次性添加多个元素
        static <E> list<E> of (E...elements)
        使用前提:
                当集合中存储的元素个数已经确定了,不再改变时使用
         注意:
            1.of方法只适用于list接口,Set接口,Map接口,不适用于接口的实现类
            2.of方法的返回值是一个不能改变的集合,集合不能再使用add,put方法添加元素,会抛出异常
            3.Set接口和Map接口在调用of方法的时候,不能有重复的元素,否则会抛出异常。

 */
public class Demo05 {
    public static void main(String[] args) {
        List<String> a = List.of("a", "b", "c", "d", "a");
        System.out.println(a);//[a, b, c, d, a]
       // a.add("c");//UnsupportedOperationException 不支持操作异常

        Set<String> b = Set.of("a", "b", "c");
    //    Set<String> b1 = Set.of("a", "b", "c","a");//set不允许重复,非法参数异常:IllegalArgumentException
        System.out.println(b);//[c, b, a]

        Map<String, Integer> map = Map.of("张三", 18, "李四", 19, "王五", 20);
        System.out.println(map);//{王五=20, 李四=19, 张三=18}
        // map.put("赵四",30);//UnsupportedOperationException 不支持操作异常


    }
}

2.2 Debug追踪

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

 */
public class Demo06Debug {
    public static void main(String[] args) {
      /*  int  a = 10;
        int b = 20;
        int sum = a +b;
        System.out.println(sum);*/

      /*  for (int i = 0; i < 3; i++) {
            System.out.println(i);

        }*/
      print();

    }
    private  static void print(){
        System.out.println("HelloWorld!");
        System.out.println("HelloWorld!");
        System.out.println("HelloWorld!");
        System.out.println("HelloWorld!");
        System.out.println("HelloWorld!");
    }
}

三、模拟斗地主洗牌发牌

3.1分析在这里插入图片描述

3.2 代码实现

/*
    斗地主综合案例:有序版本
    1.准备牌
    2.洗牌
    3.发牌
    4.排序
    5.看牌

 */
public class Poker {
    public static void main(String[] args) {
        //1.准备牌
        //创建一个Map集合,存储牌的索引和组装好的牌
        HashMap<Integer,String> poker = new HashMap<>();
        //创建一个list集合存储牌的索引
        ArrayList<Integer> pokerIndex = new ArrayList<>();

        //定义两个集合存储花色和牌号
        List<String> colors = List.of("♥","♦","♠","♣");
        List<String> numbers= List.of("2","A","K","Q","J","10","9","8","7","6","5","4","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,color + number);
                pokerIndex.add(index);
                index++;
            }

        }
//        System.out.println(poker);
//        System.out.println(pokerIndex);
       /* 2.洗牌
        使用Collections中的方法shuffle(List)
      */
        Collections.shuffle(pokerIndex);
        System.out.println(pokerIndex);
        /*
        3.发牌
         */
        //定义四个集合,存储玩家牌的索引,和底牌索引
        ArrayList<Integer> player01 = new ArrayList<>();
        ArrayList<Integer> player02 = new ArrayList<>();
        ArrayList<Integer> player03 = new ArrayList<>();
        ArrayList<Integer> diPai = new ArrayList<>();

        //遍历存储牌索引的List集合,获取每一个牌的索引
        for (int i = 0; i < pokerIndex.size(); i++) {
            Integer in = pokerIndex.get(i);
            if(i >= 51){
                //给底牌发牌
                diPai.add(in);
            }else if (i % 3 == 0){
                //给玩家1发牌
                player01.add(in);

            }else if (i % 3 == 1){
                //给玩家2发牌
                player02.add(in);
            }else if(i % 3 == 2 ){
                //给玩家3发牌
                player03.add(in);
            }
            
        }
        /*
        4.排序
        使用Collections中的sort(List)方法
         */
        Collections.sort(player01);
        Collections.sort(player02);
        Collections.sort(player03);
        Collections.sort(diPai);
        //5.看牌
        lookPoker("刘德华",poker,player01);
        lookPoker("周润发",poker,player02);
        lookPoker("周星驰",poker,player03);
        lookPoker("底牌",poker,diPai);

    }

     /*
        5.定义一个看牌的方法,提高代码复用性
        参数:
            String name;   玩家姓名
            HashMap<Integer,String> poker    存储扑克牌的集合
            ArrayList<Integer> list(diPai)  存储玩家 和底牌的list集合
         查表法:
                遍历玩家或者底牌集合,获取牌的索引,
                使用牌的索引去Map集合中,找到对应的牌
         */
     public static void lookPoker(String name,HashMap<Integer,String> poker,ArrayList<Integer> list){
         //输出玩家名称,不换行
         System.out.print(name + ": ");
         //遍历玩家或者底牌集合,获取牌的索引
         for (Integer key : list) {
             String value = poker.get(key);
             System.out.print(value+" ");


         }
         System.out.println();//打印完每一个玩家的牌,换行


     }

}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值