3/12day09_Map集合_集合的嵌套_斗地主发牌案例_冒泡

2020-03-12  本文已影响0人  蹦蹦跶跶的起床啊

反馈和复习

a.比较器口诀: 升序 前-后(源码)
b.为什么保证元素的唯一性.重写hashCode和equals
    因为Hash表结构,底层就是根据hashCode和equals来判断两个元素是否重复
1.Collection: 7+1
2.List: 7+1+4
    ArrayList: 7+1+4
    LinkedList: 7+1+4+8
3.Set:7+1
    HashSet:7+1   无序
    LinkedHashSet:7+1 有序
    TreeSet:7+1 无序(有自然顺序的)
4.Collections    
     shuffle(List list); 打乱集合顺序
     sort(List list); 对集合元素进行排序(默认升序)
     sort(List list,Comparator 比较器); 自定义排序规则(升序 前-后)

今日内容

Map集合(接口)[重点]

概述

所有实现类都没有特有方法 ,是个双列集合



特点:

Map的实现类及其特点

Map接口三个常见的实现类:

重点:
Map中为了保证键的唯一性, 如果键是自定义类型,必须重写键的hashCode和equals方法

Map的通用方法

tips:
使用put方法时,若指定的键(key)在集合中没有,则没有这个键对应的值,返回null,并把指定的键值添加到集合中;
若指定的键(key)在集合中存在,则返回值为集合中键对应的值(该值为替换前的值),并把指定键所对应的值,替换成指定的新值。

Map的遍历[非常重要]

迭代器,增强for,for循环都不可用. 因为 Map和Collection没有关系, 没有索引

第一种方式称为:以键找值
public class TestMap01 {
    public static void main(String[] args) {
        //第一种遍历方式:以键找值
        //1.创建一个Map的实现类对象
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        //2.添加几个
        map.put("张三", 18);
        map.put("李四", 28);
        map.put("王五", 38);
        map.put("赵六", 48);
        map.put("前妻", 8);
        map.put("王八", 88);
        //3.获取所有的键
        Set<String> keys = map.keySet();
        //4.遍历这个keys集合
        for (String key : keys) {
            //5.以键找值
            Integer value = map.get(key);
            System.out.println(key + "..." + value);
        }
    }
}    
第二种方式称为:键值对方式
public class TestMap02 {
    public static void main(String[] args) {
        //第一种遍历方式:以键找值
        //1.创建一个Map的实现类对象
        HashMap<String, Integer> map = new HashMap<String, Integer>();
        //2.添加几个
        map.put("张三", 18);
        map.put("李四", 28);
        map.put("王五", 38);
        map.put("赵六", 48);
        //Map集合遍历的第二种方式:键值对方式
        //3.获取Map中所有的键值对
        Set<Map.Entry<String, Integer>> entries = map.entrySet();
        //4.遍历这个entries集合
        for (Map.Entry<String, Integer> entry : entries) {
            //5.从entry中取出键和值
            String key = entry.getKey();
            Integer value = entry.getValue();
            //6.打印
            System.out.println(key+"..."+value);
        }
    }
}
    

HashMap存储自定义类型

HashMap存储键位自定义类型时,必须在自定义类型中重写hash和equals方法

需求:
    创建一个Map,学生作为键, 家庭住址作为值。
    HashMap<Student,String>
public class TestDemo {
    public static void main(String[] args) {
        //创建一个Map,学生作为键, 家庭住址作为值。
        //1.创建集合
        HashMap<Student,String> map = new HashMap<Student, String>();
        //2.添加数据
        map.put(new Student("jack",12),"北京中关村");
        map.put(new Student("rose",16),"南京中关村");
        map.put(new Student("marry",20),"天津中关村");
        map.put(new Student("tom",12),"东京中关村");
        //3.打印
        //{Student{name=jack,age=12}="北京中关村",键=值,键=值,键=值}
        System.out.println(map);
        //4.我要修改rose的地址
        map.put(new Student("rose",16),"广东东莞");
        System.out.println(map);
    }
}
结论:
    如果键是自定义类型,为了保证键的唯一性,必须重写hashCode和equals方法     

LinkedHashMap介绍

HashMap底层采用哈希表结构,是无序的.
LinkedHashMap底层采用链表+哈希表结构,是有序的

public class LinkedHashMapDemo {
    public static void main(String[] args) {
        LinkedHashMap<String, String> map = new LinkedHashMap<String, String>();
        map.put("邓超", "孙俪");
        map.put("李晨", "范冰冰");
        map.put("刘德华", "朱丽倩");
        Set<Entry<String, String>> entrySet = map.entrySet();
        for (Entry<String, String> entry : entrySet) {
            System.out.println(entry.getKey() + "  " + entry.getValue());
        }
    }
}

TreeMap集合

TreeMap底层采用红黑树结构
TreeMap也是无序的, 会按照键的自然顺序默认升序
如果存储的键为自定义类型,则必须使用比较器进行排序,否则TreeMap的自然顺序会不知道按照对象的什么来排序.

public static void main(String[] args) {
    TreeMap<Integer, String> map = new TreeMap<Integer, String>();
    map.put(1,"张三");
    map.put(4,"赵六");
    map.put(3,"王五");
    map.put(6,"酒八");
    map.put(5,"老七");
    map.put(2,"李四");
    System.out.println(map);
}
 
控制台的输出结果为:
{1=张三, 2=李四, 3=王五, 4=赵六, 5=老七, 6=酒八}

自然排序

扩展:
Arrays.sort | Collections.sort
| TreeSet | TreeMap 按照如下进行
如果键是数值类型,按照键值大小升序排序,如果是字符串类型, 先按照首字母码值,再按次字母码值

如果想要采用从大到小等自定义规则排序, 则使用比较器Comparator 排序就可以

在TreeMap中可以使用如下代码,使用其构造方法

public class Student {
    private int age;
    private String name;
    //省略get/set..
    public Student() {}
    public Student(int age, String name) {
        this.age = age;
        this.name = name;
    }
    @Override
    public String toString() {
        return "Student{" +
                "age=" + age +
                ", name='" + name + '\'' +
                '}';
    }
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return age == student.age &&
                Objects.equals(name, student.name);
    }
    @Override
    public int hashCode() {
        return Objects.hash(age, name);
    }
}
public static void main(String[] args) {
    TreeMap<Student, String> map = new TreeMap<Student, String>(new Comparator<Student>
() {
        @Override
        public int compare(Student o1, Student o2) {
            //先按照年龄升序
            int result = o1.getAge() - o2.getAge();
            if (result == 0) {
                //年龄相同,则按照名字的首字母升序
                return o1.getName().charAt(0) - o2.getName().charAt(0);
            } else {
                //年龄不同,直接返回结果
                return result;
            }
        }
    });
    map.put(new Student(30, "jack"), "深圳");
    map.put(new Student(10, "rose"), "北京");
    map.put(new Student(20, "tom"), "上海");
    map.put(new Student(10, "marry"), "南京");
    map.put(new Student(30, "lucy"), "广州");
    System.out.println(map);
}
控制台的输出结果为:
{
  Student{age=10, name='marry'}=南京, 
  Student{age=10, name='rose'}=北京, 
  Student{age=20, name='tom'}=上海, 
  Student{age=30, name='jack'}=深圳, 
  Student{age=30, name='lucy'}=广州
}

Map集合练习[重点]

需求: 输入一个字符串中每个字符出现次数。

public class MapTest {
public static void main(String[] args) {
        //友情提示
        System.out.println("请录入一个字符串:");
        String line = new Scanner(System.in).nextLine();
        // 定义 每个字符出现次数的方法
        findChar(line);
    }
    private static void findChar(String line) {
        //1:创建一个集合 存储  字符 以及其出现的次数
        HashMap<Character, Integer> map = new HashMap<Character, Integer>();
        //2:遍历字符串
        for (int i = 0; i < line.length(); i++) {
            char c = line.charAt(i);
            //判断 该字符 是否在键集中
            if (!map.containsKey(c)) {//说明这个字符没有出现过
                //那就是第一次
                map.put(c, 1);
            } else {
                //先获取之前的次数
                Integer count = map.get(c);
                //count++;
                //再次存入  更新
                map.put(c, ++count);
            }
        }
        System.out.println(map);
    }
}

集合嵌套[非常重要]

总述:任何集合内部都可以存储其它任何集合

List嵌套List

public class Test{
    public static void main(String[] args){
        /*
            假如有两个班的学生姓名,它们分别存储在两个集合中:
        */
        //第一个班
        ArrayList<String> list1 = new ArrayList<>();
        list1.add("迪丽热巴");
        list1.add("古力娜扎");
        list1.add("柳岩");
        list1.add("杨幂");
        
        //第二个班
        ArrayList<String> list2 = new ArrayList<>();
        list2.add("蔡徐坤");
        list2.add("杨坤");
        list2.add("陈伟霆");
        list2.add("李易峰");
        
        //将两个集合存储到一个集合中
        ArrayList<ArrayList<String>> allList = new ArrayList<>();
        allList.add(list1);
        allList.add(list2);
        
        System.out.println(allList);
        //遍历allList,取出每个ArrayList
        for(ArrayList<String> list : allList){
            //遍历每个班的ArrayList
            for(String s : list){
                System.out.println(s);
            }
        }
    }
    
}
 

List嵌套Map

public class Test{
    public static void main(String[] args){
        /*
            有两个班的学员,分别存储在两个Map中
        */
        //第一个班:
        Map<String,String> map1 = new HashMap<>();
        map1.put("it001","迪丽热巴");
        map1.put("it002","古力娜扎");
        
        //第二个班:
        Map<String,String> map2 = new HashMap<>();
        map2.put("heima001","蔡徐坤");
        map2.put("heima002","李易峰");
        
        //将两个班的map存储到一个ArrayList中
        ArrayList<Map<String,String>> allList = new ArrayList<>();
        allList.add(map1);
        allList.add(map2);
        
        //遍历allList,取出每个Map
        for(Map<String,String> map : allList){
            //遍历map
            Set<String> keys = map.keySet();
            for(String key : keys){
                System.out.println(key + " - " + map.get(key));
            }
        }
    }

Map嵌套Map

public class Test{
    public static void main(String[] args){
        /*
        有两个班,班号分别为:"黑马188期"和"黑马189期",两个班学员的姓名分别存储在两个Map中
        */
        //"黑马188期":
        Map<String,String> map1 = new HashMap<>();
        map1.put("it001","迪丽热巴");
        map1.put("it002","古力娜扎");
        
        //"黑马189期":
        Map<String,String> map2 = new HashMap<>();
        map2.put("heima001","蔡徐坤");
        map2.put("heima002","李易峰");
        
        //将两个班的Map连同对应的"班号"一同存储在一个Map中
        Map<String,Map<String,String>> allMap = new HashMap<>();
        allMap.put("黑马188期",map1);
        allMap.put("黑马189期",map2);
        
        //遍历allMap
        Set<String> keys = allMap.keySet();
        for(String k : keys){
            System.out.println(k + ":");
            //取出对应的map
            Map<String,String> map = allMap.get(k);
            //遍历map
            Set<String> keys2 = map.keySet();
            for(String k2 : keys2){
                System.out.println(k2 + " = " + map.get(k2));
            }
        }
    }
}

模拟斗地主洗牌发牌[重点]

案例介绍

需求: 模拟斗地主发牌,看牌(但是不打牌)

图解斗地主洗牌

分析

步骤分析:
1.准备 编号和牌 组成的Map集合
2.准备一副牌(54个编号)
3.洗牌(打乱集合)
4.发牌(遍历集合)
5.排序(sort方法)
6.转牌(以键找值)
7.打印给用户看

斗地主洗牌代码实现

public class TestDouDiZhu {
    public static void main(String[] args) {
        //1.准备 编号和牌 组成的Map集合
        LinkedHashMap<Integer, String> map = new LinkedHashMap<Integer, String>();
        //a.花色 4种
        String[] colors = {"♠", "♥", "♣", "♦"};
        //b.数值 13种
        String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
        //c.编号变量
        int id = 1;
        //d.组合牌
        for (String num : nums) {
            for (String color : colors) {
                String card = color + num;
                //保存到map集合中
                map.put(id, card);
                id++;
            }
        }
        //e.单独添加大小王
        map.put(53, "小S");
        map.put(54, "大S");

        //2.准备一副牌(54个编号)
        ArrayList<Integer> cards = new ArrayList<Integer>();
        for (int i = 1; i < 55; i++) {
            cards.add(i);
        }
        //3.洗牌(打乱集合)
        Collections.shuffle(cards);
        //4.发牌(遍历集合)
        ArrayList<Integer> player1 = new ArrayList<Integer>();
        ArrayList<Integer> player2 = new ArrayList<Integer>();
        ArrayList<Integer> player3 = new ArrayList<Integer>();
        ArrayList<Integer> diPai = new ArrayList<Integer>();
        //遍历集合
        //此处不能使用增强for
        for (int i = 0; i < cards.size() - 3; i++) {
            //取出每一张牌
            Integer card = cards.get(i);
            //给谁呢?????????????????????????????????
            //i = 0 3 6 p1
            //i = 1 4 7 p2
            //i = 2 5 8 p3
            if (i % 3 == 0) {
                player1.add(card);
            } else if (i % 3 == 1) {
                player2.add(card);
            }else{
                player3.add(card);
            }
        }

        //最后张三留给底牌
        diPai.add(cards.get(53));
        diPai.add(cards.get(52));
        diPai.add(cards.get(51));
        //5.排序(sort方法)
        Collections.sort(player1);
        Collections.sort(player2);
        Collections.sort(player3);
        Collections.sort(diPai);

        //6.看牌
        lookCards(player1,map);
        lookCards(player2,map);
        lookCards(player3,map);
        lookCards(diPai,map);

    }
    //看牌方法
    public static void lookCards(ArrayList<Integer> idCards, LinkedHashMap<Integer, String> map) {
        //遍历
        for (Integer idCard : idCards) {
            String card = map.get(idCard);
            System.out.print(card+" ");
        }
        System.out.println();
    }
}

冒泡排序算法(工具类已经写好了)

介绍

n个数据一共执行 n-1轮, 每一轮, 需要执行 n-1次

过程图解


冒泡排序动态图.gif

代码实现

/*
    冒泡排序:
        一种排序的方式,对要进行排序的数据中相邻的数据进行两两比较,将较大的数据放在后面,
        依次对所有的数据进行操作,直至所有数据按要求完成排序
 */
public class ArrayDemo {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {7, 6, 5, 4, 3};
        System.out.println("排序前:" + Arrays.toString(arr));
 
        // 这里减1,是控制每轮比较的次数
        for (int x = 0; x < arr.length - 1; x++) {
            // -1是为了避免索引越界,-x是为了调高比较效率
            for (int i = 0; i < arr.length - 1 - x; i++) {
                  //如果前>后   
                  if (arr[i] > arr[i + 1]) {
                    int temp = arr[i];
                    arr[i] = arr[i + 1];
                    arr[i + 1] = temp;
                }
            }
        }
        System.out.println("排序后:" + Arrays.toString(arr));
    }
}

数结构特点小结

数组特点:查询快,增删慢

单向链表特点:查询慢,增删快

栈特点:先进后出

队列特点:先进先出

哈希表特点:查询速度快

今日小结

1.Map接口定义的共性方法【必须掌握】
        put(键,值);
        remove(键);
        put(重复的键,值);
        get(键)
            
        containsKey(键);
        containsValue(值);
2.Map各种实现类的遍历方式(a.以键找值 b.键值对方式)【必须掌握】
        a.以键找值
            Set<K> keys = map.keySet(); //获取所有键的集合
            for(K key : keys){ //遍历所有的键
                V value = map.get(key)//以键找值
                //打印
                sout(key,value);    
            }
        b.键值对方式
            Set<Map.Entry<K,V>> entrys = map.entrySet();//获取所有的键值对的集合
            for(Map.Entry<K,V> entry : entrys){//遍历这个键值对集合
                K key = entry.getKey();//获取键值对中的键和值  
                V value = entry.getValue();//获取键值对中的键和值  
                //打印
                sout(key,value);   
            }
    
3.集合嵌套【难点,开发中见的不多】
    a。List套List:
        ArrayList<ArrayList<String>> arr;
    b。List套Map
        ArrayList<HashMap<String,Integer>> map
    c。Map套Map
        HashMap<String,HashMap<String,Integer>> map
4.斗地主牌【必须掌握】
    至少3遍!!!    
    
5.冒泡排序【理解】
      a。理解冒泡过程
      b。算法背下来
            for(int i = 0;i<arr.length-1;i++){
                for(int j = 0;j<arr.length-1-i;j++){
                    if(arr[j]>arr[j+1]){
                        int temp = arr[j];
                        arr[j] = arr[j+1];
                        arr[j+1] = temp;
                    }
                }  
            }
    ```    





上一篇下一篇

猜你喜欢

热点阅读