JavaSE学习day18(Map集合)

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/weixin_42135811/article/details/102527617

18.01_集合框架(Map集合概述和特点)

  • A:Map接口概述
  • 查看API可以知道:
    • 将键映射到值的对象
    • 一个映射不能包含重复的键
    • 每个键最多只能映射到一个值
  • B:Map接口和Collection接口的不同
  • Map是双列的,Collection是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构值针对键有效,跟值无关;Collection集合的数据结构是针对元素有效

18.02_集合框架(Map集合的功能概述)

  • A:Map集合的功能概述
  • a:添加功能
    • V put(K key,V value):添加元素。
    • 如果键是第一次存储,就直接存储元素,返回null
    • 如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
import java.util.HashMap;
import java.util.Map;

public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);
      System.out.println(map);
      //{李四=24, 张三=23, 王五=25, 赵六=26}
   }
}
  • b:删除功能
    • void clear():移除所有的键值对元素
    • V remove(Object key):根据键删除键值对元素,并把值返回
import java.util.HashMap;
import java.util.Map;

public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

      Integer i = map.remove("张三");
      System.out.println(i);//23
      System.out.println(map);
      //{李四=24, 王五=25, 赵六=26}
   }
}
  • c:判断功能
    • boolean containsKey(Object key):判断集合是否包含指定的键
    • boolean containsValue(Object value):判断集合是否包含指定的值
    • boolean isEmpty():判断集合是否为空
import java.util.HashMap;
import java.util.Map;

public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

      Integer i = map.remove("张三");
      System.out.println(i);//23
      System.out.println(map.containsKey("张三"));//false 判断是否包含传入的键
      System.out.println(map.containsValue(25));//true 判断是否包含传入的值
      System.out.println(map);
      //{李四=24, 王五=25, 赵六=26}
   }
}
  • d:获取功能
    • Set<Map.Entry<K,V>entrySet():
    • V get(Object key):根据键获取值
    • Set<KkeySet():获取集合中所有键的集合
    • Collection<Vvalues():获取集合中所有值的集合
  • e:长度功能
    • int size():返回集合中的键值对的个数
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

      Collection<Integer> c = map.values();
      System.out.println(c); //[24, 23, 25, 26]
      System.out.println(map.size());//4
   }
}

18.03_集合框架(Map集合的遍历之键找值)

  • A:键找值思路:
  • map集合不能直接迭代,没有Iterator方法
  • 获取所有键的集合
  • 遍历键的集合,获取到每一个键
  • 根据键找值
    在这里插入图片描述
  • B:案例演示
  • Map集合的遍历之键找值
  • 使用迭代器遍历
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 通过查看Map集合的方法发现Map集合没有iterator方法,那么双列集合的迭代如下
 */
public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

      Integer i = map.get("张三");//根据键获取值
      System.out.println(i);//23

      //要遍历首先获取所有的键
      Set<String> set = map.keySet();//获取所有键的集合
      Iterator<String> it = set.iterator();//获取迭代器
      while(it.hasNext()){//判断集合中是否有元素
         String key = it.next(); // 获取每一个键
         Integer value = map.get(key); //根据键或取钱值
         System.out.print(key +" "+ value +" ");
         //李四 24 张三 23 王五 25 赵六 26
      }
   }
}
  • 使用增强for循环遍历
import java.util.HashMap;
import java.util.Map;

/**
 * 通过查看Map集合的方法发现Map集合没有iterator方法,那么双列集合的迭代如下
 */
public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

      Integer i = map.get("张三");//根据键获取值
      System.out.println(i);//23

      for (String key : map.keySet()) { //map.keySet是索引的键的集合
         System.out.print(key +" "+ map.get(key) +" ");
         //李四 24 张三 23 王五 25 赵六 26
      }
   }
}

18.04_集合框架(Map集合的遍历之键值对对象找键和值)

  • A:键值对对象找键和值思路:
  • 获取所有键值对对象的集合
  • 遍历键值对对象的集合,获取到每一个键值对对象
  • 根据键值对对象找键和值
    在这里插入图片描述
  • B:案例演示
  • Map集合的遍历之键值对对象找键和值
import java.util.HashMap;
import java.util.Map;

/**
 * 通过查看Map集合的方法发现Map集合没有iterator方法,那么双列集合的迭代如下
 */
public class Main {
   public static void main(String[] args) {
      Map<String,Integer> map = new HashMap<>();
      map.put("张三",23);
      map.put("李四",24);
      map.put("王五",25);
      map.put("赵六",26);

        //1.用迭代器的方法
//      //Map.Entry说明Entry是Map的内部接口,
//		//将键和值封装成了Entry对象,并存储在Set集合中
//      Set<Map.Entry<String,Integer>> entrySet = map.entrySet();
//      //获取每一个对象
//      Iterator<Map.Entry<String,Integer>> it = entrySet.iterator();
//      while (it.hasNext()){
//         Map.Entry<String,Integer> en = it.next();
//         String key = en.getKey(); //根据键值对象获取键
//         Integer value = en.getValue(); //根据键值对象获取值
//         System.out.print(key+" "+value+" ");
//         //李四 24 张三 23 王五 25 赵六 26
//      }

      //2.用增强for循环的方法
      for (Map.Entry<String,Integer> en : map.entrySet()) {
         System.out.print(en.getKey()+" "+en.getValue()+" ");
         //李四 24 张三 23 王五 25 赵六 26 
      }

   }
}
  • C:源码分析

18.05_集合框架(HashMap集合键是Student值是String的案例)

  • A:案例演示
  • HashMap集合键是Student值是String的案例
import java.util.Objects;

public class Student {
    private String name;
    private int age;
    public Student(){
        super();
    }
    public Student(String name,int age){
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

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

    public int getAge(){
        return age;
    }

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

    @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(name, age);
    }
}
import java.util.HashMap;
import java.util.Map;

public class Main {
   /**
    * 键是学生对象,代表每一个学生
    * 值是字符串对象,代表学生归属地
    * @param args
    */
   public static void main(String[] args) {
      Map<Student,String> hm = new HashMap<>();
      hm.put(new Student("张三",23),"北京");
      hm.put(new Student("张三",23),"上海");
      hm.put(new Student("李四",23),"广州");
      hm.put(new Student("王五",23),"深圳");

      System.out.println(hm);
      //{Student{name='张三', age=23}=北京,
      // Student{name='王五', age=23}=深圳,
      // Student{name='张三', age=23}=上海,
      // Student{name='李四', age=23}=广州}
      //有重复键,需要在student重写hashcode和equals
      //重写之后打印结果为
      //{Student{name='张三', age=23}=上海,
      // Student{name='王五', age=23}=深圳,
      // Student{name='李四', age=23}=广州}
   }
}

18.06_集合框架(LinkedHashMap的概述和使用)

  • A:案例演示
  • LinkedHashMap的特点
    • 底层是链表实现的可以保证怎么存就怎么取
import java.util.LinkedHashMap;

public class Main {
   public static void main(String[] args) {
      LinkedHashMap<String,Integer> lnm = new LinkedHashMap<>();
      lnm.put("张三",23);
      lnm.put("李四",24);
      lnm.put("王五",25);

      System.out.println(lnm);
      //{张三=23, 李四=24, 王五=25}
   }
}

18.07_集合框架(TreeMap集合键是Student值是String的案例)

  • A:案例演示
  • TreeMap集合键是Student值是String的案例
  • 案例一
import java.util.TreeMap;

public class Main {
   public static void main(String[] args) {
      TreeMap<Student,String> tm = new TreeMap<>();
      tm.put(new Student("张三",23),"北京");
      tm.put(new Student("李四",24),"上海");
      tm.put(new Student("王五",25),"广州");
      tm.put(new Student("赵六",26),"深圳");

      System.out.println(tm);
      //报错 ClassCastException 没有实现compare接口不能比较
      //student要实现compare接口
      //{Student{name='张三', age=23}=北京,
      // Student{name='李四', age=24}=上海,
      // Student{name='王五', age=25}=广州,
      // Student{name='赵六', age=26}=深圳}
   }
}
import java.util.Objects;

public class Student implements Comparable<Student>{
    private String name;
    private int age;
    public Student(){
        super();
    }
    public Student(String name,int age){
        super();
        this.name = name;
        this.age = age;
    }

    public String getName() {
        return name;
    }

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

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

    public int getAge(){
        return age;
    }

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

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

    public int compareTo(Student o){
        int num = this.age - o.age;//以年龄为主要条件
        return num == 0 ? this.name.compareTo(o.name) : num;
        //以姓名为次要条件
    }
}
  • 案例二
import java.util.Comparator;
import java.util.TreeMap;

public class Main {
   public static void main(String[] args) {
      TreeMap<Student,String> tm = new TreeMap<>(new Comparator<Student>(){
         @Override
         public int compare(Student s1, Student s2) {
            int num = s1.getName().compareTo(s2.getName());
            return num == 0 ? s1.getAge()-s2.getAge() : num;
         }
      });
      tm.put(new Student("张三",23),"北京");
      tm.put(new Student("李四",24),"上海");
      tm.put(new Student("王五",25),"广州");
      tm.put(new Student("赵六",26),"深圳");

      System.out.println(tm);
      //{Student{name='张三', age=23}=北京, 
      // Student{name='李四', age=24}=上海, 
      // Student{name='王五', age=25}=广州, 
      // Student{name='赵六', age=26}=深圳} 已排序
   }
}

18.08_集合框架(统计字符串中每个字符出现的次数)

  • A:案例演示
  • 需求:统计字符串中每个字符出现的次数
import java.util.HashMap;

public class Main {
   /**
    * 需求:统计字符串中每个字符出现的次数
    * 1.定义一个需要被统计字符的字符串
    * 2.将字符串转换为字符数组
    * 3.定义双列集合,存储字符串中字符以及字符出现的次数
    * 4.遍历字符数组获取每一个字符,并将字符存储在双列集合中
    * 5.存储过程中要做判断,如果集合中不包含这个键,就将该字符当做键,值为1存储
    * 6.如果集合中不包含这个键,就降值加1存储
    * 7.打印双列集合获取字符出现的次数
    * @param args
    */
   public static void main(String[] args) {
      String str = "adcaacddca";
      char[] arr = str.toCharArray();
      HashMap<Character,Integer> hm = new HashMap<>();
      //HashMap效率最高
      for(char c : arr){
         /*if(!hm.containsKey(c)){
            hm.put(c,1);
         }else{
            hm.put(c,hm.get(c)+1);
         }*/
         hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c) + 1);
      }
      for(Character key : hm.keySet()){
         System.out.print(key+"="+hm.get(key)+" ");
         //a=4 c=3 d=3
      }
   }
}

18.09_集合框架(集合嵌套之HashMap嵌套HashMap)

  • A:案例演示
  • 集合嵌套之HashMap嵌套HashMap
import java.util.HashMap;

public class Main {
   /**
    * 需求:HashMap嵌套HashMap
    * 88期基础班定义成一个双列集合,键是学生对象,值是学生归属地
    * 99期基础班定义成一个双列集合,键是学生对象,值是学生归属地
    * 为了便于统一管理,把这些班级对象添加到课堂集合中
    * @param args
    */
   public static void main(String[] args) {
      HashMap<Student,String> hm88 = new HashMap<>();
      hm88.put(new Student("张三",23), "北京");
      hm88.put(new Student("李四",24), "北京");
      hm88.put(new Student("王五",25), "上海");
      hm88.put(new Student("赵六",26), "广州");

      HashMap<Student,String> hm99 = new HashMap<>();
      hm99.put(new Student("小明",17), "北京");
      hm99.put(new Student("小华",18), "北京");
      hm99.put(new Student("小红",19), "上海");
      hm99.put(new Student("小花",16), "广州");

      HashMap<HashMap<Student,String>,String> hm = new HashMap<>();
      hm.put(hm88,"第88期基础班");
      hm.put(hm99,"第99期基础班");

      //遍历双列集合
      for(HashMap<Student,String> h : hm.keySet()){ //hm.keySet()代表的是双列集合中键的集合
         String value = hm.get(h); //get(h)根据键对象获取值对象
         for(Student key : h.keySet()){ //h.keySet()获取集合中所有的学生键对象
            String value2 = h.get(key);
            System.out.println(key+" "+value2+" "+value);
//            Student{name='张三', age=23} 北京 第88期基础班
//            Student{name='李四', age=24} 北京 第88期基础班
//            Student{name='王五', age=25} 上海 第88期基础班
//            Student{name='赵六', age=26} 广州 第88期基础班
//            Student{name='小明', age=17} 北京 第99期基础班
//            Student{name='小花', age=16} 广州 第99期基础班
//            Student{name='小华', age=18} 北京 第99期基础班
//            Student{name='小红', age=19} 上海 第99期基础班
         }
      }
   }
}

18.10_集合框架(HashMap和Hashtable的区别)

  • A:面试题
  • HashMap和Hashtable的共同点
    • 底层都是哈希算法,都是双列集合
  • HashMap和Hashtable的区别
    • Hashtable是JDK1.0版本出现的,是线程安全的
    • 效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
    • Hashtable不可以存储null键和null值
    • HashMap可以存储null键和null值

18.11_集合框架(Collections工具类的概述和常见方法讲解)

  • A:Collections类概述
  • 针对集合操作 的工具类
  • B:Collections成员方法
public static <T> void sort(List<T> list)
public static <T> int binarySearch(List<?> list,T key)
public static <T> T max(Collection<?> coll)
public static void reverse(List<?> list)
public static void shuffle(List<?> list)
import java.util.ArrayList;
import java.util.Collections;

public class Main {
   public static void main(String[] args) {
      ArrayList<String> list = new ArrayList<>();
      list.add("a");
      list.add("c");
      list.add("d");
      list.add("b");
      Collections.sort(list);
      System.out.println(list);//[a, b, c, d] 排序

      ArrayList<String> list1 = new ArrayList<>();
      list1.add("a");
      list1.add("c");
      list1.add("d");
      list1.add("f");
      System.out.println(Collections.binarySearch(list1,"d"));//2 二分查找

      ArrayList<String> list2 = new ArrayList<>();
      list2.add("a");
      list2.add("c");
      list2.add("d");
      list2.add("g");
      System.out.println(Collections.max(list2));//g 找最大值
      Collections.reverse(list2);
      System.out.println(list2);//[g, d, c, a] 反转集合
      Collections.shuffle(list2);
      System.out.println(list2);//[d, g, a, c] 随机置换可用于洗牌
   }
}

18.12_集合框架(模拟斗地主洗牌和发牌)

  • A:案例演示
  • 模拟斗地主洗牌和发牌,牌没有排序
import java.util.ArrayList;
import java.util.Collections;

public class Main {
   /**
    * 模拟斗地主洗牌和发牌
    * 1.创建集合对象,将扑克牌存进去
    * 2.洗牌,调用Collections的shuffle方法
    * 3.发牌
    * 4.看牌
    * @param args
    */
   public static void main(String[] args) {
      String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
      String[] color = {"红桃","黑桃","梅花","方块"};
      ArrayList<String> poker = new ArrayList<>();

      //拼接字符串,拼接花色和数字
      for(String s1 : color){
         for(String s2 : num){
            poker.add(s1.concat(s2));//contact连接两个字符串
         }
      }
      poker.add("小王");
      poker.add("大王");
      //洗牌
      Collections.shuffle(poker);
      //发牌
      ArrayList<String> gaojin = new ArrayList<>();
      ArrayList<String> longwu = new ArrayList<>();
      ArrayList<String> me = new ArrayList<>();
      ArrayList<String> dipai = new ArrayList<>();//留三张给底牌

      for(int i = 0; i < poker.size(); i++){
         if(i >= poker.size() - 3){
            dipai.add(poker.get(i));//将三张底牌存储在底牌集合中
         }else if(i % 3 == 0){
            gaojin.add(poker.get(i));
         }else if(i % 3 == 1){
            longwu.add(poker.get(i));
         }else{
            me.add(poker.get(i));
         }
      }

      //看牌
      System.out.println(gaojin);
      System.out.println(longwu);
      System.out.println(me);
      System.out.println(dipai);
   }
}

18.13_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的原理图解)

  • A:画图演示
  • 画图说明排序原理
    在这里插入图片描述

18.14_集合框架(模拟斗地主洗牌和发牌并对牌进行排序的代码实现)

  • A:案例演示
  • 模拟斗地主洗牌和发牌并对牌进行排序的代码实现
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.TreeSet;

public class Main {
   /**
    * 模拟斗地主洗牌和发牌
    * 1.创建集合对象,将扑克牌存进去
    * 2.洗牌,调用Collections的shuffle方法
    * 3.发牌
    * 4.看牌
    * @param args
    */
   public static void main(String[] args) {
      String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
      String[] color = {"红桃","黑桃","梅花","方块"};
      HashMap<Integer, String> hm = new HashMap<>();//存储索引和扑克牌
      ArrayList<Integer> list = new ArrayList<>(); //存储索引
      int index = 0;

      //拼接扑克牌将索引和扑克牌存储在hm中
      for(String s1 : num){  //获取数字
         for(String s2 : color){   //获取颜色
            hm.put(index, s2.concat(s1));//contact连接两个字符串
            list.add(index);  //将0-51索引添加到集合中
            index++;
         }
      }
      hm.put(index,"小王");
      list.add(index);   //将52索引添加到集合中
      index++;
      hm.put(index,"大王");
      list.add(index);  //将53索引添加到集合中
      //洗牌
      Collections.shuffle(list);
      //发牌
      TreeSet<Integer> gaojin = new TreeSet<>();
      TreeSet<Integer> longwu = new TreeSet<>();
      TreeSet<Integer> me = new TreeSet<>();
      TreeSet<Integer> dipai = new TreeSet<>();//留三张给底牌

      for(int i = 0; i < list.size(); i++){
         if(i >= list.size() - 3){
            dipai.add(list.get(i));//将三张底牌存储在底牌集合中
         }else if(i % 3 == 0){
            gaojin.add(list.get(i));
         }else if(i % 3 == 1){
            longwu.add(list.get(i));
         }else{
            me.add(list.get(i));
         }
      }

      //看牌
      lookPoker(hm,gaojin,"高进");
      lookPoker(hm,longwu,"龙五");
      lookPoker(hm,me,"我");
      lookPoker(hm,dipai,"底牌");
   }

   /**
    * 1.返回类型void
    * 2.参数列表HashMap,TreeSet,String name
    */
   public static void lookPoker(HashMap<Integer,String> hm,TreeSet<Integer> ts,String name){
      System.out.print(name+"的牌是:");
      for(Integer i : ts){
         System.out.print(hm.get(i)+" ");
      }
      System.out.println();
   }
}

18.15_集合框架(泛型固定下边界)

  • ? super E
import java.util.ArrayList;
import java.util.Comparator;
import java.util.TreeSet;

import com.heima.bean.BaseStudent;
import com.heima.bean.Student;

public class Demo2_Genric {
	/**
	 * 泛型固定下边界
	 * ? super E  
	 * 
	 * 泛型固定上边界
	 * ? extends E
	 */
	public static void main(String[] args) {
		//demo1();
		TreeSet<Student> ts1 = new TreeSet<>(new CompareByAge());
		ts1.add(new Student("张三", 33));
		ts1.add(new Student("李四", 13));
		ts1.add(new Student("王五", 23));
		ts1.add(new Student("赵六", 43));
		
		TreeSet<BaseStudent> ts2 = new TreeSet<>(new CompareByAge());
		ts2.add(new BaseStudent("张三", 33));
		ts2.add(new BaseStudent("李四", 13));
		ts2.add(new BaseStudent("王五", 23));
		ts2.add(new BaseStudent("赵六", 43));
		
		System.out.println(ts2);
	}

	public static void demo1() {
		ArrayList<Student> list1 = new ArrayList<>();
		list1.add(new Student("张三", 23));
		list1.add(new Student("李四", 24));
		
		ArrayList<BaseStudent> list2 = new ArrayList<>();
		list2.add(new BaseStudent("王五", 25));
		list2.add(new BaseStudent("赵六", 26));
		
		list1.addAll(list2);
	}
}

class CompareByAge implements Comparator<Student> {
	@Override
	public int compare(Student s1, Student s2) {
		int num = s1.getAge() - s2.getAge();
		return num == 0 ? s1.getName().compareTo(s2.getName()) :  num;
	}
}

18.16_集合框架(总结)

  • A:Collection
  • List ( 存取有序,有索引,可以重复)
    • ArrayList:底层是数组实现的,线程不安全,查找修改快,增删慢
    • LinkedList:底层是链表实现的,线程不安全,查找修改慢,增删快
    • Vector:底层是数组实现的,线程安全,增删改查都慢
    • 如果查找和修改多用ArrayList,如果增删多用LinkedList,如果都多用ArrayList
  • Set(存取无序,无索引,不可以重复)
    • HashSet:底层是哈希算法实现
      • LinkedHashSet:底层是链表实现但是也可保证元素唯一,和HashSet一样
    • TreeSet:底层是二叉树算法实现
    • 一般在开发的时候不需要对存储的元素排序,所以在开发的时候大多用HashSet,HashSet效率比较高
    • TreeSet在面试的时候问的比较多,问你有几种排序方式,和几种排序方式的区别
      在这里插入图片描述
  • B:Map
  • HashMap:底层是哈希算法,针对键
    • LinkedHashMap:底层是链表,针对键
  • TreeMap:底层是二叉树算法,针对键
  • 开发者HashMap用的比较多

猜你喜欢

转载自blog.csdn.net/weixin_42135811/article/details/102527617
今日推荐