Java-Map,斗地主案例

Map集合

1.1 概述

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

  • Collection接口,定义了单列集合规范,每次存储一个元素,单个元素,孤立存在

  • Map接口,定义了双列集合的规范,每次存储一对儿元素,成对存在:

    Map<key,value>,key和value的数据类型,可以相同也可以不同

    将键映射到值的对象,一个映射不能包含重复的键;每个键最多只能映射到一个值。

    键唯一,但是值可以重复,一个键对应一个值,通过键可以找到值

1.2 Map常用子类
  • HashMap<K,V>:存储数据采用的**哈希表**结构,元素的存取顺序不能保证一致。由于要保证键的唯一、不重复,需要重写键的hashCode()方法、equals()方法。

    底层:哈希表 无须集合,存取顺序不一致

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

    底层:哈希表+链表 有序集合,存取顺序一致

1.3 Map接口中常用方法
  • public V put(K key, V value): 把指定的键与指定的值添加到Map集合中。

    /*
    返回值:V
    	在进行存储的时候,如果key值不存在,则会存入,并且返回null
    	如果key重复,就会用新的Value去替换原来的Value,然后返回被替换的value值
    */
    package Demo06;
    
    import java.util.HashMap;
    import java.util.Map;
    
    public class DemoMap {
        public static void main(String[] args) {
            show01();
        }
        private static void show01() {
            Map<String,String> map = new HashMap<>();
            String v = map.put("吃饭","喝茶");
            System.out.println(v);  //null
            String v2 = map.put("吃饭","喝饮料");
            System.out.println(v2);  //喝茶
        }
    }
    
  • public V remove(Object key): 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值

    map.put("告辞","拜拜");
    map.put("吃饭","喝饮料");
    map.put("喝水","吃饭");
    map.put("百事","可口");
    map.put("椰奶","椰汁");
    System.out.println(map);    //{吃饭=喝饮料, 百事=可口, 椰奶=椰汁, 喝水=吃饭, 告辞=拜拜}
    String v = map.remove("吃饭");
    System.out.println(v);  //喝饮料
    
  • public V get(Object key) 根据指定的键,在Map集合中获取对应的值。

    String v1 = map.get("百事");
    System.out.println(v1);     //可口
    
  • boolean containsKey(Object key) 判断集合中是否包含指定的键。

    boolean boo = map.containsKey("告辞");
    System.out.println(boo);    //true
    
  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

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

1.4 Map集合遍历方式
  1. 获取Map中所有的键,由于键是唯一的,所以返回一个Set集合存储所有的键。方法提示:keyset()
  2. 遍历键的Set集合,得到每一个键。
  3. 根据键,获取键所对应的值。方法提示:get(K key)
  • public Set<K> keySet(): 获取Map集合中所有的键,存储到Set集合中。

    package Demo06;
    
    import java.util.*;
    
    public class DemoMap {
        public static void main(String[] args) {
            Map<String, String> map = new HashMap<>();
            map.put("告辞", "拜拜");
            map.put("吃饭", "喝饮料");
            map.put("喝水", "吃饭");
            map.put("百事", "可口");
            map.put("椰奶", "椰汁");
    
            Set<String> set = map.keySet();
            System.out.println(set);    //[吃饭, 百事, 椰奶, 喝水, 告辞]
            
            //迭代器
            Iterator<String> it = set.iterator();
            while (it.hasNext()) {
                String key = it.next();
                System.out.println(key+':'+ map.get(key));
            }
            //增强for
            for (String i: set) {
                System.out.println(i+':'+map.get(i));
            }
        }
    }
    /*
    吃饭:喝饮料
    百事:可口
    椰奶:椰汁
    喝水:吃饭
    告辞:拜拜
    */
    
  • public Set<Map.Entry<K,V>> entrySet(): 获取到Map集合中所有的键值对对象的集合(Set集合)。

    package Demo06;
    
    import java.util.*;
    
    public class DemoMap {
        public static void main(String[] args) {
            Map<String, String> map = new HashMap<>();
            map.put("告辞", "拜拜");
            map.put("吃饭", "喝饮料");
            map.put("喝水", "吃饭");
            map.put("百事", "可口");
            map.put("椰奶", "椰汁");
    
            Set<Map.Entry<String,String>> setmap = map.entrySet();
            System.out.println(setmap); //[吃饭=喝饮料, 百事=可口, 椰奶=椰汁, 喝水=吃饭, 告辞=拜拜]
    
            Iterator<Map.Entry<String,String>> it = setmap.iterator();
            while(it.hasNext()){
                Map.Entry<String,String> entry = it.next();
                System.out.println(entry.getKey()+ ':'+entry.getValue());
            }
    
            for (Map.Entry<String,String> i: setmap) {
                System.out.println(i.getKey()+ ':'+i.getValue());
            }
        }
    }
    /*
    吃饭:喝饮料
    百事:可口
    椰奶:椰汁
    喝水:吃饭
    告辞:拜拜
    */
    
1.5 Map集合存储自定义集合

作为键的值如果为自定义类型,比如所Person类,那么就需要重写hashCode方法和equals方法,来保证不唯一

//Perosn
package Demo06;

import java.util.Objects;

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

    @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(age, name);
    }
}
package Demo06;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

public class DemoPerson {
    public static void main(String[] args) {
        HashMap<Person,String> map = new HashMap<>();
        map.put(new Person(18,"Rain"),"北京");
        map.put(new Person(23,"Jerry"),"上海");
        map.put(new Person(36,"Tom"),"郑州");
        map.put(new Person(24,"Nacy"),"长沙");
        map.put(new Person(18,"Rain"),"武汉");
        //当重写了两个方法后,相同的Person就不会出现

        Iterator<Map.Entry<Person, String>> iterator = map.entrySet().iterator();
        while(iterator.hasNext()){
            Map.Entry<Person,String> entry = iterator.next();
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
    }
}

1.6 LinkedHashMap集合

LinkedHashMap继承了HashMap集合

底层为哈希表+链表(记录顺序)

package Demo06;

import java.util.HashMap;
import java.util.LinkedHashMap;

public class DemoLinkedHashMap {
    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("a","d");
        System.out.println(map);    //{a=d, b=b, c=c}
        //不允许重复,但是存入输出数据顺序不同

        LinkedHashMap<String,String> link = new LinkedHashMap<>();
        link.put("a","a");
        link.put("c","c");
        link.put("b","b");
        link.put("a","d");
        System.out.println(link);   //{a=d, c=c, b=b}
        不允许重复,但是存入输出数据顺序相同
    }
}
1.7 HashTable

跟HashMap一样,底层是哈希表

和HashMap不同的是,任何的非null对象都能作为键或则值

HashMap和HashTable的区别:

  1. table是一个线程安全的集合,是单线程的,速度比较慢
  2. map是一个线程不安全的集合,是多线程的,速度比较快
  3. 之前学的所有的集合都是可以存储null值的,不论是键还是值
  4. table不能存储空值
package Demo06;

import java.util.HashMap;
import java.util.Hashtable;

public class DemoHashTable {
    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(null,"a");
        table.put("b",null);
        table.put(null,null);
        System.out.println(table);  //会报出空指针异常,Exception in thread "main" java.lang.NullPointerException
    }
}
1.8 Debug追踪

Debug调试程序:

​ 可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug

使用方式:

  1. 用My Eclipse,在行号右边点击,出现大红圆点,来添加断点(哪里有bug添加在哪里)
  2. 添加断点后,右键使用Debug执行程序,程序就会停留在第一个断点处
  3. F8:逐行执行语句;F7:进入到方法中;Shift+F8:跳出方法;F9:跳到下一个断点(如果没有下一个断点,就停止程序);Ctrl+F2:退出Debug模式,停止程序;

斗地主案例升级版(到手的牌有序)

分析:
  1. 准备牌

    54张牌,其中包括两张特殊的牌:大小王

    其他52张牌:

    • 定义以一个数组/集合,包括四种花色:桃、心、梅、方

    • 定义以一个数组/集合,面值:A、2、3、…、K

      将两个集合组合起来变成剩余的52张

    利用map集合键值对的形式,key为0-53的数字,value对应不同的牌

    然后创建一个普通的集合list,用来存放0-53的数字

  2. 洗牌:使用集合工具类Collections的方法

    static void shuffle(List<?> List)使用指定的随机源对指定的列表进行置换

    随机打乱集合中的元素;注意,这个时候打乱集合list的顺序,也就是将集合中0-53打乱

  3. 摸牌:要求1人17张牌,剩余三张作为底牌,一人一张轮流发牌:集合的索引(0-53)%3

    定义4个集合,分别存储3个玩家的牌和底牌

    索引%3,有三个值(0,1,2)

    索引>=51,给底牌发牌

    这个时候发给每个人的值是0-53当中的数字

  4. 排序:使用Collections中的soft(list)方法

  5. 看牌:通过每个人手中的数字,作为map集合的键,对应到map集合的value,然后将value值取出打印

package DouDiZhu;

import java.util.*;

public class DemoDDZ_2 {
    public static void main(String[] args) {
        //定义两个数组分别存花色和数值
        String[] color = {"♠","♥","♣","♦"};
        String[] number = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
        //将大小王先放到扑克集合中
        Map<Integer,String> map = new LinkedHashMap<>();
        map.put(52,"SmallJoker");
        map.put(53,"BigJoker");

        //循环嵌套两个数组,组装52张牌,并把牌放到扑克集合当中
        //一个键对应一个值,例如52,对应小王,53对应大王
        int i = 0;
        while(i <= 51){
            for (String numbers : number) {
                for (String colors : color) {
                    map.put(i,colors+numbers);
                    i++;
                }
            }
        }

        //定义一个poker ArrayList集合,里面存放的是map集合当中的键
        ArrayList<Integer> poker = new ArrayList<>();
        for (int j = 0; j <= 53; j++) {
            poker.add(j);
        }
        //打乱顺序
        Collections.shuffle(poker);

        //定义四个集合来,代表三个人和底牌集合
        ArrayList<Integer> people1 = new ArrayList<>();
        ArrayList<Integer> people2 = new ArrayList<>();
        ArrayList<Integer> people3 = new ArrayList<>();
        ArrayList<Integer> lastPoker = new ArrayList<>();


        //发牌
        int k = 0;
        while (k <= 50){
            if (k%3 == 0){
                people1.add(poker.get(k));
            }else if (k%3 == 1){
                people2.add(poker.get(k));
            }else if (k%3 == 2){
                people3.add(poker.get(k));
            }
            k++;
        }

        //把最后的三张牌作为底牌,放到底牌集合中
        lastPoker.add(poker.get(51));
        lastPoker.add(poker.get(52));
        lastPoker.add(poker.get(53));

        //对每个人手中的牌进行排序,注意:这个时候每个人手中的其实是0-53中的数值,每个数字代表一张牌,现在是对数字进行排序
        Collections.sort(people1);
        Collections.sort(people2);
        Collections.sort(people3);
        Collections.sort(lastPoker);

        //看牌,通过获取每个人手中的数字,拿到map集合中,获取每个数字对应的是什么牌
        System.out.println("三千七百万:"+ print(map,people1));
        System.out.println("反手一个超级加倍:"+ print(map,people2));
        System.out.println("闷声发大财慈善家:"+ print(map,people3));
        System.out.println("底牌:"+ print(map,lastPoker));
    }

    public static ArrayList<String> print(Map<Integer,String> map,ArrayList<Integer> list){
        ArrayList<String> strList = new ArrayList<>();
        for (Integer i:list) {
            String value = map.get(i);
            strList.add(value);
        }
        return strList;
    }

}

/*
三千七百万:[♥3, ♠4, ♣4, ♣6, ♠7, ♥8, ♣8, ♥9, ♠10, ♦J, ♠Q, ♠A, ♥A, ♣A, ♠2, ♦2, SmallJoker]
反手一个超级加倍:[♦3, ♦4, ♠5, ♥5, ♣5, ♠6, ♦6, ♥7, ♦7, ♠8, ♣9, ♦10, ♥J, ♦Q, ♣K, ♣2, BigJoker]
闷声发大财慈善家:[♠3, ♣3, ♥4, ♦5, ♥6, ♦8, ♠9, ♦9, ♠J, ♣J, ♥Q, ♣Q, ♠K, ♥K, ♦K, ♦A, ♥2]
底牌:[♣7, ♥10, ♣10]
*/
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值