Java中的Map

1.Map概述

Map中的集合,元素是成对存在的(理解为夫妻)。每个元素由键与值两部分组成,通过键可以找对所对应的值。

创建Map集合的对象:因为Map是接口,不能直接创建对象,所以我们使用多态的方式来创建.在这里我们可以创建实现类HashMap的对象

2.Map集合的功能

方法名说明
V put(Object key, V value)添加元素
V remove(Object key)根据键删除键值对元素
void clear()清空Map中所有元素
boolean containsKey(Object key)判断集合是否包含指定的键
boolean containsValue(Object value)判断集合是否包含指定的值
boolean isEmpty()判断集合是否为空
int size()获取集合长度,即集合中键个数
V get(Object key)根据键获取值
Set KeySet()获取所有键的集合
Collection values()获取所有值的集合
Set> entrySet()获取所有键值对象的集合
V getOrDefault(Object key, V defaultValue)当Map集合中有这个key时,就使用这个key对应的value值,如果没有就使用默认值defaultValue

代码演示:

1.Map集合的基本功能

package com.zzu.map;
import java.util.HashMap;
import java.util.Map;
public class Demo1 { public static void main(String[] args) { Map map=new HashMap<>();//创建HashMap对象
        map.put("name","jh");//key value
        map.put("age","nineteen");
        map.put("sex","male");
        System.out.println(map.remove("age"));//nineteen
        System.out.println(map);
        System.out.println(map.containsKey("name"));//true
        System.out.println(map.containsValue("nineteen"));//false age已经remove
        System.out.println(map.isEmpty());//false
        System.out.println(map.size());//2
        map.clear();//清空
        System.out.println(map.isEmpty());//true
        System.out.println(map.size());//0
    }
}

输出结果:

nineteen
{sex=male, name=jh}
true
false
false
2
true
0

2.Map集合的获取功能

package com.zzu.map;
import java.util.*;
public class Demo2 { public static void main(String[] args) { Map map=new HashMap<>();
        map.put("name","jh");
        map.put("age","nineteen");
        map.put("sex","male");
        System.out.println(map.get("sex"));//获取male
        System.out.println("----------");
        System.out.println(map.keySet());//获取键集合
        Set ketSet=map.keySet();
        for(String s:ketSet){ System.out.println(s);
        }
        System.out.println("----------");
        System.out.println(map.values());//获取值集合
        Collection collection=map.values();
        for(String s:collection){ System.out.println(s);
        }
        System.out.println("----------");
        System.out.println(map.entrySet());//获取所有键值对象集合
        Set> setMapEntry = map.entrySet();
        System.out.println(setMapEntry);
    }
}

输出结果:

male
----------
[sex, name, age]
sex
name
age
----------
[male, jh, nineteen]
male
jh
nineteen
----------
[sex=male, name=jh, age=nineteen]
[sex=male, name=jh, age=nineteen]

3.Map的getOrDefault()方法

package com.zzu.map;
import java.util.HashMap;
import java.util.Map;
public class Demo3 { public static void main(String[] args) { Map map=new HashMap<>();
        map.put("name","jh");
        map.put("age","nineteen");
        map.put("sex","male");
        System.out.println(map.getOrDefault("name", "111"));//jh
        System.out.println(map.getOrDefault("time", "666"));//666
    }
}

3.巩固拓展

1.HashMap存储自定义对象实现键值唯一

重点:放在HashMap集合key部分的元素,以及放在HashSet集合中的元素,需要同时重写hashCode和equals方法

IDEA在源码中已经在HashMap中重写了上述两种方法

import java.util.Objects;
/*
类Student 重写其equals(),toString()方法 满足:
    (1).比学号、姓名、性别
    (2).System.out.println(new Student())输出信息:"学号:,姓名:(性别)"
    (3).数组存放,实现头插、学号序输出、不重复的输入输出
 */
public class Student { private String id;
    private String name;
    private String sex;
    public Student() { }
    public Student(String id, String name, String sex) { this.id = id;
        this.name = name;
        this.sex = sex;
    }
    public String getId() { return id;
    }
    public void setId(String id) { this.id = id;
    }
    public String getName() { return name;
    }
    public void setName(String name) { this.name = name;
    }
    public String getSex() { return sex;
    }
    public void setSex(String sex) { this.sex = sex;
    }
    //重写之后的equals方法 比较的就是对象内部的属性值
    @Override
    public boolean equals(Object o) { if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return Objects.equals(id, student.id) && Objects.equals(name, student.name) && Objects.equals(sex, student.sex);
    }
    //重写hashCode方法
    @Override
    public int hashCode() { return Objects.hash(id, name, sex);
    }
    //重写之后的toString方法 打印的是属性值
    @Override
    public String toString() { return  "学号:" + id  + ", 姓名:" + name + "("+sex+")";
    }
}
import java.util.*;
public class Test { public static void main(String[] args) { //测试toString equals方法
        Student s1 = new Student("202107","jh","m");
        Student s2 = new Student("202107","yy","f");
        //重写之后的toString() 打印的是内容
        System.out.println("s1.toString():"+s1.toString());
        System.out.println("s1.toString():"+s2.toString());
        //重写之后的equals方法 比较的是内容
        System.out.println("s1.equals(s2):"+s1.equals(s2));
        //1.创建一个链式集合
        LinkedList list = new LinkedList<>();
        //2.数组生成7个学生信息
        String[][] arrStu = {{"202101","张三","m"},{"202105","李四","m"},{"202101","张三","m"},
                {"202101","张三","m"},{"202103","王小","f"},{"202102","王小","f"},{"202105","李四","m"}};
        //3.生成学生对象 并且放入集合中
        for (int i = 0; i < arrStu.length; i++) { Student stu = new Student(arrStu[i][0],arrStu[i][1],arrStu[i][2]);
            list.add(stu);
        }
        //4.头部插入对象 并输出list对象信息
        Student s = new Student("202104","小七","f");
        list.add(0,s);
        list.forEach(str-> System.out.println(str));
        //5.学号序输出list对象信息
        list.sort((a,b)->a.getId().compareTo(b.getId()));
        System.out.println("--------idSort--------");
        list.forEach(str-> System.out.println(str));
        //6.创建一个set集合 接收数据 重写hashCode方法保证键值唯一
        Set set = new HashSet<>(list);
        System.out.println("----------Set---------");
        set.forEach(str-> System.out.println(str));
        //添加数据  返回值看是否添加成功
        Student stu = new Student("202101","张三","m");
        boolean result = set.add(stu);
        System.out.println("添加数据:"+result);
        //打印最终结果
        System.out.println("--------endSet--------");
        set.forEach(str-> System.out.println(str));
    }
}

输出内容:

s1.toString():学号:202107, 姓名:jh(m)
s1.toString():学号:202107, 姓名:yy(f)
s1.equals(s2):false
学号:202104, 姓名:小七(f)
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202103, 姓名:王小(f)
学号:202102, 姓名:王小(f)
学号:202105, 姓名:李四(m)
--------idSort--------
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202101, 姓名:张三(m)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)
学号:202104, 姓名:小七(f)
学号:202105, 姓名:李四(m)
学号:202105, 姓名:李四(m)
----------Set---------
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202104, 姓名:小七(f)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)
添加数据:false
--------endSet--------
学号:202101, 姓名:张三(m)
学号:202105, 姓名:李四(m)
学号:202104, 姓名:小七(f)
学号:202102, 姓名:王小(f)
学号:202103, 姓名:王小(f)

2.用到getOrDefault()方法的例题

class Solution{ public String evaluate(String s, List> knowledge) { Map mp = new HashMap();
        for(List list:knowledge){ mp.put(list.get(0),list.get(1));//添加键值对
        }
        StringBuilder sb = new StringBuilder();
        char[] ch = s.toCharArray();//这里将字符串对象中的字符转换为一个字符数组
        for(int i = 0,t;(t=i) if(ch[i]=='('){ while(ch[i]!=')') i++;
                sb.append(mp.getOrDefault(s.substring(t+1,i),"?"));//键值存在否 选择性添加
            }else{ sb.append(ch[i]);
            }
        }
        return sb.toString();
    }
 }

3.较为综合的练习题

这一题充分展现了JAVA的”便捷“,不信你大可试试c/c++,说实话真的STL中map感觉比java好用多了,用java有时候还不如直接模拟哈希,写题自觉用c/c++

class Solution { public int rearrangeCharacters(String s, String target) { char[] sChar = s.toCharArray();//字符串转换为字符数组
        char[] tChar = target.toCharArray();//java字符串不同于c/c++ 不存在字符组成 需要特定方法charAt()获取 如果遍历次数过多这样转换可能好点
        //创建两个哈希表计数
        Map sCounts = new HashMap<>();
        Map tCounts = new HashMap<>();
        for(Character ch:tChar){ tCounts.put(ch, tCounts.getOrDefault(ch, 0) + 1);//感觉很妙么 c++直接map[key]++
        }
        for(Character ch:sChar){ if(tCounts.containsKey(ch)){//只有在target中出现的字符才会影响最大副本数
                sCounts.put(ch, sCounts.getOrDefault(ch, 0) + 1);
            }
        }
        int ans = Integer.MAX_VALUE;//记录副本数
        for (Map.Entry entry : tCounts.entrySet()) {//遍历记录
            char c = entry.getKey();//获取键
            int count = entry.getValue();//在target中出现次数
            int totalCount = sCounts.containsKey(c) ? sCounts.get(c) : 0;//如果s中根本不存在 则直接赋予0
            ans = Math.min(ans, totalCount / count);//所有字符对应的最大副本数中的最小值即为使用s中的字符可以形成的target的最大副本数
            if (ans == 0) {//如果ans等于零 则直接返回
                return 0;
            }
        }
        return ans;
    }
}