java高级篇5——Map集合、HashMap集合、LinkedHashMap集合

1、Map集合

  • java.util.Map集合与Collection集合是两个体系,Collection是单列集合。
  • Map集合的特点:
  1. Map集合是一个双列集合,一个元素包含两个值:key和value。
  2. Map集合中的元素key和value的数据类型可以相同也可以不同
  3. Map集合中的元素key是不允许重复的,value是可以重复的。
  4. Map集合中的元素key和value是一一对应的。

2、Map常用子类

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

3、Map接口中的常用方法

  • public V put(K key, V value):将指定的键与值添加到Map集合中,返回值为V,若key不重复,则返回V是null,若key重复,将新的value替换重复的value,则返回被替换后的value值。
  • public V remove(Object key):将指定的键对应的键值对元素在Map中删除,返回被删元素的值,若key存在,则返回被删除的值,若key不存在,则返回null。
  • public V get(Object key):根据指定的键,在Map集合中获得对应的值,若key存在,返回对应的value值,若key不存在,返回null。
  • boolean containsKey(Object key):判断集合中是否包含指定的键,若包含,返回true,否则,返回false。
public class Demo01Map {
    public static void main(String[] args) {
        //创建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);//b1:true

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

        //创建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);//v1:165

        Integer v2 = map.get("迪丽热巴");
        System.out.println("v2:"+v2);//v2:null
  
        //创建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}

        //int v2 = map.remove("林志颖");//自动拆箱  NullPointerException
        Integer v2 = map.remove("林志颖");
        System.out.println("v2:"+v2);//v2:null

        System.out.println(map);//{赵丽颖=168, 杨颖=165}

        //创建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("冷锋","龙小云");
        map.put("杨过","小龙女");
        map.put("尹志平","小龙女");
        System.out.println(map);//{杨过=小龙女, 尹志平=小龙女, 李晨=范冰冰2, 冷锋=龙小云}
    }
}

4、Map集合遍历——方法一:键找值方式

java高级篇5——Map集合、HashMap集合、LinkedHashMap集合_第1张图片

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

/*
    Map集合的第一种遍历方式:通过键找值的方式
    Map集合中的方法:
         Set 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集合对象
        Map<String,Integer> map = new HashMap<>();
        map.put("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

        //1.使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
        Set<String> set = map.keySet();

        //2.遍历set集合,获取Map集合中的每一个key
        //使用迭代器遍历Set集合
        Iterator<String> it = set.iterator();
        while (it.hasNext()){
            String key = it.next();
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : set){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
        System.out.println("-------------------");
        //使用增强for遍历Set集合
        for(String key : map.keySet()){
            //3.通过Map集合中的方法get(key),通过key找到value
            Integer value = map.get(key);
            System.out.println(key+"="+value);
        }
    }
}

5、Map集合遍历——方法二:使用Entry键值对对象

java高级篇5——Map集合、HashMap集合、LinkedHashMap集合_第2张图片

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

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

    Map集合中的方法:
        Set> 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("赵丽颖",168);
        map.put("杨颖",165);
        map.put("林志玲",178);

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

        //2.遍历Set集合,获取每一个Entry对象
        //使用迭代器遍历Set集合
        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(Map.Entry<String,Integer> entry:set){
            //3.使用Entry对象中的方法getKey()和getValue()获取键与值
            String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key+"="+value);
        }
    }
}

6、HashMap存储自定义类型键值

  • Map集合保证key唯一,作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一。
import java.util.HashMap;
import java.util.Map;

public class HashMapPersonDemo {
    public static void main(String[] args) {
        HashMap<Person,String> map = new HashMap<>();  //将自定义类型Person作为集合的key
        map.put(new Person("XX1",18),"法国");
        map.put(new Person("XX2",19),"英国");
        map.put(new Person("XX3",20),"美国");
        map.put(new Person("XX1",18),"中国");  //Person类重写了equals和hashCode方法,不允许重复,所以会覆盖第一个

        for(Map.Entry<Person,String> entry : map.entrySet()){
            Person key = entry.getKey();
            String value = entry.getValue();
            System.out.println(key + "→" + value);
        }
    }
}
程序结果:
Person{name='XX1', age=18}→中国
Person{name='XX2', age=19}→英国
Person{name='XX3', age=20}→美国

7、LinkedHashMap集合

  • java.uti.LinkedHashMap extends HashMap
  • LinkedHashMap集合由Map接口的哈希表和链表实现,具有可预知的迭代顺序,有序
  • 底层原理:**哈希表+链表(**记录元素的顺序)
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());   //有序,存储和取出顺序一致
        }
    }
}
程序结果:
邓超  孙俪
李晨  范冰冰
刘德华  朱丽倩

8、Hashtable集合

  • java.util.Hashtable集合 implements Map接口
  • HashMap底层是哈希表,是一个线程不安全的集合,是多线程集合,速度快
  • Hashtable底层也是哈希表,是一个线程安全的集合,是单线程集合,速度慢
  • HashMap集合(和之前学的所有集合)可以存储null值,null键
  • Hashtable集合不能存储null值,null键,若存储null会导致空指针异常NullPointerException
  • Hashtable和Vector集合一样,在jdk1.2版本后被更先进的集合(HashMap,ArrayList)取代了。
  • Hashtable的子类Properties依然活跃在历史舞台,Properties集合是唯一一个yu与IO流相结合的集合。

9、Map集合练习

  • 计算一个字符串中每个字符出现的次数
  • 分析
    java高级篇5——Map集合、HashMap集合、LinkedHashMap集合_第3张图片
import java.util.HashMap;
import java.util.Scanner;

public class CountCharactersDemo {
    public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        System.out.println("请输入一个字符串:");
        String str = sc.next();
        HashMap<Character,Integer> map = new HashMap<>();
        for(char c : str.toCharArray()){   //遍历字符数组
            if(map.containsKey(c)){   //如果该字符以及在map中,则将统计值+1
                Integer value = map.get(c);
                value++;
                map.put(c,value);
            }else{    //否则如果不在,则将该字符添加进去,统计值为1
                map.put(c,1);
            }
        }
        for(Character key : map.keySet()){  //根据键找值的方式遍历map集合
            Integer value = map.get(key);
            System.out.println(key + "="+ value);
        }
    }
}

10、JDK9对集合添加的优化——of方法

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

public class OfDemo {
    public static void main(String[] args) {
        List<String> list = List.of("a","b","c","a","d");  //List接口使用of方法
        System.out.println(list);   //[a, b, c, a, d] List可重复
        //list.add("q");  //UnsupportedOperationException 不支持操作异常

//        Set set = Set.of("a","b","c","a","d"); //IllegalArgumentException非法参数异常,不允许有重复元素
        Set<String> set = Set.of("a","b","c","d");
//        set.add("x");  //UnsupportedOperationException
        System.out.println(set);  //[b, a, d, c]  Set不可重复,无序

//        Map map = Map.of("张三",18,"李四",19,"张三",20);  //IllegalArgumentException,不允许key重复
        Map<String,Integer> map = Map.of("张三",18,"李四",19,"张三三",20);  //IllegalArgumentException,不允许key重复
//        map.put("XX",22);  //UnsupportedOperationException
        System.out.println(map);  //{李四=19, 张三三=20, 张三=18}  Map key不可重复,无序
    }
}

11、Debug追踪

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

12、斗地主案例——有序版

  • 需求分析:
    java高级篇5——Map集合、HashMap集合、LinkedHashMap集合_第4张图片
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;

public class DouDiZhu02 {
    public static void main(String[] args) {
        //1 准备牌
        HashMap<Integer,String> poker = new HashMap<>();  //用于存储牌的索引和组装好的牌
        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 ++;
        for(String number : numbers){  //嵌套循环组装牌
            for (String color : colors) {
                poker.put(index,color+number);
                pokerIndex.add(index);
                index ++;
            }
        }
        //2 洗牌
        Collections.shuffle(pokerIndex);  //打乱牌的索引
        //3 发牌
        ArrayList<Integer> player01 = new ArrayList<>(); //定义四个集合存储三个玩家和底牌的牌索引
        ArrayList<Integer> player02 = new ArrayList<>();
        ArrayList<Integer> player03 = new ArrayList<>();
        ArrayList<Integer> diPai = new ArrayList<>();
        for (int i = 0; i < pokerIndex.size(); i++) {
            Integer in = pokerIndex.get(i);  //获取每个索引值
            if(i>=51){
                diPai.add(in);
            }else if(i%3==0){      //添加进去的是牌的索引
                player01.add(in);
            }else if(i%3==1){
                player02.add(in);
            }else if(i%3==2){
                player03.add(in);
            }
        }
        //4 排序
        Collections.sort(player01);
        Collections.sort(player02);
        Collections.sort(player03);
        Collections.sort(diPai);
        //5 看牌
        lookPoker("玩家1",poker,player01);
        lookPoker("玩家2",poker,player02);
        lookPoker("玩家3",poker,player03);
        lookPoker("底牌",poker,diPai);
    }
    //定义一个查看牌的方法
    private 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();  //打印一个玩家,换行
    }
}
程序结果:
玩家122 ♥A ♦K ♦Q ♣1099886554433 
玩家2 小王 ♥2 ♦A ♠K ♠Q ♣Q ♠J ♦10876655433 
玩家3 大王 ♠2 ♠A ♣A ♥K ♣K ♥Q ♥J ♣J ♦J ♠101099877 
底牌 ♥764 

你可能感兴趣的:(java高级篇)