Day15

一. Map集合

  1. 定义

    • Map集合是一个双列集合,以键值对的形式存在
    • 将键和值捆绑到一起存放(Map.Entry)
    • 一个映射不能包含重复的键
    • 如果出现相同的键,会用新的值覆盖老的值
    • 每个键最多只能映射到一个值
  2. Map接口和Collection接口的不同

    • Map是双列的,Collection是单列的
    • Map集合的数据结构针对键有效, 跟值无关, Collection 集合的数据结构是针对元素有效
  3. 常用功能

    • 添加方法
      • V put(K key , V value): 添加元素
        • 如果键是第一次存储, 直接存储元素,返回null
        • 如果键不是第一个存在, 就用值把以前的值替换掉,返回以前的值
    • 删除方法
      • void clear() : 移除所有的键值对元素
      • V remove(Object key) : 根据键删除键值对元素, 并把值返回
    • 判断方法
      • boolean containsKey(Object key) : 判断集合是否包含指定的键
      • boolean containsValue(Object value): 判断集合是否包含指定的值
      • boolean isEmpty: 判断集合是否为空
    • 获取方法
      • Set> entrySet() : 获取所有的键值对
      • V get(Object key) : 根据键获取值
      • Set keySet() : 获取集合中所有键的集合
      • Collection values() : 获取集合中所有值的集合
      • int size() : 返回集合中键值对的个数
  4. 演示

    public static void main(String[] args) {
     Map map = new HashMap<>();
     
     //添加方法
     map.put("小红", 18);
     map.put("小明", 24);
     map.put("小辉", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     System.out.println(map);
     
     //判断键是否存在
     boolean flg = map.containsKey("小红");
     System.out.println(flg);
     //判断值是否存在
     flg = map.containsValue(18);
     System.out.println(flg);
     //判断集合是否为空
     flg = map.isEmpty();
     System.out.println(flg);
     //根据键获取值
     Integer i = map.get("小王");
     System.out.println(i);
     //获取集合中元素的个数
     int size = map.size();
     System.out.println(size);
     //获取集合中所有的键值对
     Set> entrySet = map.entrySet();
     System.out.println(entrySet);
     //获取集合中所有键
     Set keyset = map.keySet();
     System.out.println(keyset);
     //获取集合中所有的值
     Collection valueSet = map.values();
     System.out.println(valueSet);
     
    }
    

二. Map集合的遍历

  1. 获取所有键的集合的遍历

    • 通过keySet方法获取到所有键的Set集合
    • 演示
    public static void main(String[] args) {
     Map map = new HashMap<>();
     
     map.put("小红", 18);
     map.put("小明", 24);
     map.put("小辉", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Set keyset = map.keySet();
     Iterator it = keyset.iterator();
     while (it.hasNext()) {
         String key = it.next();
         Integer value = map.get(key);
         System.out.println("键:"+key+" 值:"+value);
     }
    }
    
  2. 获取所有的值的遍历

    • 通过values方法获取所有值的Collection集合
    • 演示
    public static void main(String[] args) {
     Map map = new HashMap<>();
     
     map.put("小红", 18);
     map.put("小明", 24);
     map.put("小辉", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Collection values = map.values();
     Iterator it = values.iterator();
     while (it.hasNext()) {
         Integer value = it.next();
         System.out.println("值:"+value);
     }
    }
    
  3. 获取所有键值对的遍历

    • 通过entrySet集合获取所有的键值对的Set集合
    • 演示
    public static void main(String[] args) {
     Map map = new HashMap<>();
     
     map.put("小红", 18);
     map.put("小明", 24);
     map.put("小辉", 26);
     map.put("小李", 19);
     map.put("小王", 18);
     
     Set> entrySet = map.entrySet();
     Iterator> it = entrySet.iterator();
     while (it.hasNext()) {
         Map.Entry entry = it.next();
         String key = entry.getKey();
         Integer value = entry.getValue();
         System.out.println("键:"+key+" 值:"+value);
     }
    }
    

三. HashMap

  1. 定义

    • 底层使用的是数组
    • HashMap就是通过我们存入的key获取到一个hash值, 经过计算之后, 获取到一个数组角标, 然后将key和value封装到一个Entry里面, 然后存入数组
    • 当数组容量不够的时候, 会自动扩容一倍
  1. 构造方法

    • HashMap()
      • 构造一个具有默认初始容量(16) 和默认加载因子(0.75)的空HashMap
    • HashMap(int initialCapacity)
      • 构造一个带指定初始容量和默认加载因子 (0.75) 的空HashMap
    • HashMap(int initialCapacity, float loadFactor)
      • 构造一个带指定初始容量和加载因子的空HashMap
    • HashMap(Map m)
      • 构造一个映射关系与制定Map相同的新HashMap
  2. 常用方法

    • put(K key, V value) : 在此映射中关联指定值与指定键
    • putAll(Map m) : 将另外一个map集合复制到此集合中
  3. 案例

    • HashMap集合键是Student值是String的案例
    • 注意
      • 如果我们需要将对象中的内容当作比较依据的话, 就必须要重写hashCode和equals方法
    • 演示
    public static void main(String[] args) {
     Map map = new HashMap<>();
     
     map.put(new Student("小红", 18), "美女");
     map.put(new Student("小李", 18), "老板的小舅子");
     
     for (Entry entry : map.entrySet()) {
         System.out.println(entry.getKey()+"::"+entry.getValue());
     }
    }
    
  4. 测试题

    • 需求: 从键盘录入一串字符, 统计字符串中每个字符出现的次数
    • 演示
    public static void main(String[] args) {
    
     Scanner scanner = new Scanner(System.in);
     
     String str = scanner.nextLine();
     
     HashMap hm = new HashMap<>();;
     
     for (int i = 0; i < str.length(); i++) {
         char ch = str.charAt(i);
         if(hm.get(ch)==null)
             hm.put(ch, 1);
         else
             hm.put(ch, hm.get(ch)+1);
     }
     System.out.println(hm);
     scanner.close();
    }
    

四. HashMap和Hashtable的区别

  1. HashMap和Hashtable的区别

    • Hashtable是JDK1.0版本出现的,是线程安全的,效率低,HashMap是JDK1.2版本出现的,是线程不安全的,效率高
    • Hashtable不可以存储null键和null值,HashMap可以存储null键和null值
  2. 案例演示

    public static void main(String[] args) {
     Map map = new HashMap<>();
    
     map.put("小红", "美女");
     map.put("小李", "老板的小舅子");
     map.put(null, null);
     
     Hashtable table = new Hashtable<>();
     table.put("小红", "美女");
     //table.put(null, null);//会报错
    }
    

五. TreeMap

  1. 定义

    • TreeMap通过比较元素的大小,对元素进行排序, 最后形成了一个树状结构
    • TreeMap中的key需要实现Comparable接口并重写compareTo方法, 或者使用Comparator比较器
    • 存入元素的时候,如果会将新添加的元素的key和集合中已经存在的元素的key比较,返回一个小于0的数,说明,新添加的元素小于已有元素, 如果返回的是一个等于0的数,说明新添加的元素等于已有元素, value覆盖, 如果返回一个大于0的数,说明新添加的元素大于已有元素
  2. 案例演示

    public static void main(String[] args) {
    
     Map map2 = new TreeMap<>();
     map2.put("小红", "美女");
     map2.put("小红", "老板的小舅子");
     System.out.println(map2);
    }
    

六. 案例(模拟洗牌和发牌)

  1. 演示

    public static void main(String[] args) {
     String[] num = {"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
     String[] color = {"方片","梅花","红桃","黑桃"};
     ArrayList poker = new ArrayList<>();
    
     for(String s1 : color) {
         for(String s2 : num) {
             poker.add(s1.concat(s2));
         }
     }
    
     poker.add("小王");
     poker.add("大王");
     
     Random random = new Random();
     int count = poker.size();
     for (int i = 0; i < count; i++) {
         int index1 = random.nextInt(count);
         int index2 = random.nextInt(count);
         Collections.swap(poker, index1, index2);
     }
     
     List one = new ArrayList<>();
     List two = new ArrayList<>();
     List three = new ArrayList<>();
     List 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)             //其他三个人依次发牌
             one.add(poker.get(i));
         else if(i%3==1)
             two.add(poker.get(i));
         else
             three.add(poker.get(i));
     }
     
     System.out.println(one);
     System.out.println(two);
     System.out.println(three);
     System.out.println(dipai);
    }
    

七. 泛型

  1. 定义

    • 泛型, 即"参数化类型" , 泛型规定了类可以使用的应用数据的类型的范围
    • 泛型,即“参数化类型”。一提到参数,最熟悉的就是定义方法时有形参,然后调用此方法时传递实参。那么参数化类型怎么理解呢?顾名思义,就是将类型由原来的具体的类型参数化,类似于方法中的变量参数,此时类型也定义成参数形式(可以称之为类型形参),然后在使用/调用时传入具体的类型(类型实参)
    • 只在编译期生效
  2. 泛型的好处

    • 提高安全性(将运行期的错误转换到编译期)
    • 省去强转的麻烦
    • 在其作用域内可以统一参数类型
  3. 泛型的基本使用

    • <>中放的必须是引用数据类型
    • 泛型可以定义来类上和方法上
  4. 泛型使用注意事项

    • 前后的泛型必须一致,或者后面的泛型可以省略不写(1.7的新特性菱形泛型)
  5. 泛型的由来

    • 类型通过Object 转型问题引入
    • 早期的Object类型可以接收任意的对象类型,但是在实际的使用中,会有类型转换的问题。也就存在这隐患,所以Java提供了泛型来解决这个安全问题。
    public class Generic {
     
     private Object object;
    
     public Object getObject() {
         return object;
     }
    
     public void setObject(Object object) {
         this.object = object;
     }
    }
    

八. 泛型的使用

  1. 把泛型定义在类上

    • 格式

      • public class 类名<泛型类型1,…>
    • 注意事项

      • 泛型类型必须是引用类型
    • 演示

      public class Generic {
         
         private T t;
      
         public Object getObject() {
             return t;
         }
      
         public void setObject(T t) {
             this.t = t;
         }
      }
      
  2. 把泛型定义在方法上

    • 格式

      • public <泛型类型> 返回类型 方法名(泛型类型 变量名)
    • 演示

      public  E method(E[] e){
         
         return e[e.length/2];
      }
      
  3. 把泛型定义在接口上

    • 格式
      • public interface 接口名<泛型类型>
      • 子类去实现接口的时候就需要给出具体的类型, 重写抽象方法的时候就可以得到具体的类型
    • 演示
    public interface Inteface {
     
     public void method(T t);
    }
    
  4. 通配符(了解)

    • 泛型通配符

      • 任意类型,如果没有明确,那么就是Object以及任意的Java类了
      public static void main(String[] args) {
         ArrayList arrayList1 = new ArrayList<>();
         
         ArrayList arrayList2 = new ArrayList<>();
         
         List list = arrayList1;
         list = arrayList2;
      }
      
    • ? extends E

      • 向下限定 E 及E的子类
    • ? super E

      • 向上限定 E及其父类

总结

  1. Map集合

    • 双列集合 一次性存两个值(key-value)
    • key-value : 键值对 映射
    • 特性:
      • key不能重复, value可以重复
  2. Map集合的方法

    • map集合的方法都是用来操作key的

    • put(key)

    • remove(key) clear

    • get(key)

  3. map集合的遍历

    • map集合没有自身的遍历方法, 要先转成set
    • keySet():获取所有的key
    • values() : 获取所有的value
    • entrySet() : 获取所有的键值对
  4. HashMap

    • 底层是数组
    • 存储时,通过key算出一个角标值, 如果当前位置上有元素, 就比较一下
      • 如果对比成功, 覆盖值
      • 如果没有成功, 挂载
    • 如果当前位置上没有元素, 直接存储
    • hashMap是如何判断是否重复的 key的地址值和hashCode和equals方法
  5. TreeMap

    • 底层是红黑树(二叉树)
    • key可以排序
    • 新元素要和老元素比较, 根据返回的结果判断存储的位置
      • 参考TreeSet
  6. HashSet和TreeSet底层用的HashMap和TreeMap

    • 其实就是将Set集合的元素当成Map集合的key
  7. 泛型

    • 设一个不是具体类型的类型
    • 好处
      • 提高代码的兼容性
      • 提高安全性,将运行期的错误提前到编译期
      • 省去强转的麻烦
      • 在一定范围统一类型
    • 泛型可以定义的地方
      • 接口, 类, 方法

作业

  1. 第一题
    • 需求:
      • 封装一个汽车类,包含String name、int speed属性,在测试类中实例化三个对象:c1,c2,c3,分别设置name为:“奥拓”,“宝马”,“奔驰”,速度分别设置为:100,200,300
      • 使用Map集合对象m1将这三个汽车类对象保存成key,然后将int型的汽车价钱作为值保存在m1的value中,上述三款汽车分别对应的价钱是10000,500000,2000000
    • 解题
      • 遍历m1的键,打印name属性
      • 通过合适的方法,求出m1中“宝马”的价格,并打印结果
      • 经过降速,所有汽车都降速到原来的80%,请打印降速后“宝马”的速度
  2. 第二题
    • 需求: 创建俩个List集合,添加一些数据,求它们的并集,差集和交集。
  3. 扩展题
    1. 第一题
      • 需求: 从键盘录入整数, 打印输入频率最高的整数, 如果有多个,就打印多个
    2. 第二题
      • 需求: 模拟斗地主洗牌发牌,并对已发好的拍进行排序(红桃A,方块A, 黑桃2.......)

你可能感兴趣的:(Day15)