黑马程序员全套Java教程_Java基础教程_集合进阶之Map(二十八)
- 5.1 Map集合概述和使用
- 5.2 Map集合的基本功能
- 5.3 Map集合的获取功能
- 5.4 Map集合的遍历(方式1)
- 5.5 Map集合的遍历(方式2)
- 案例:HashMap集合存储学生对象并遍历
- 案例:HashMap集合存储学生对象并遍历
- 案例:ArrayList集合存储HashMap元素并遍历
- 案例:HashMap集合存储ArrayList元素并遍历
- 案例:统计字符串中每个字符出现的个数
- 面试题:HashMap和Hashtable的区别?
5.1 Map集合概述和使用
- Map集合概述
(1)Interface Map<K,V> K:键的类型;V:值的类型;
(2)将键映射到值的对象;不能包含重复的键;每个键可以映射到最多一个值。
(3)举例:学生的学号和姓名
itheima001 liubei
itheima002 guanyu
itheima003 zhangfei - 创建Map集合的对象:使用多态的形式,即通过具体的实现类HashMap来创建。
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","liubei");
map.put("002","guanyu");
map.put("003","zhangfei");
map.put("003","zhaoyun");//当put的键内已经存在值,则覆盖该值
System.out.println(map);//{001=liubei, 002=guanyu, 003=zhaoyun}
}
5.2 Map集合的基本功能
方法名 | 说明 |
V put(K key,V value) | 添加元素 |
V remove(Object key) | 根据键删除键值对元素 |
void clear() | 删除所有的键值对元素 |
boolean containsKey(Objectt key) | 判断集合是否包含指定的键 |
boolean containsValue(Object value) | 判断集合是否包含指定的值 |
boolean isEmpty() | 判断集合是否为空 |
int size() | 集合的长度,也就是集合中键值对的个数 |
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","liubei");
map.put("002","guanyu");
map.put("003","zhangfei");
map.put("003","zhaoyun");//当put的键内已经存在值,则覆盖该值
System.out.println(map);//{001=liubei, 002=guanyu, 003=zhaoyun}
map.remove("003");
map.remove("004");//不报错
System.out.println(map);//{001=liubei, 002=guanyu}
System.out.println(map.containsKey("001"));//true
System.out.println(map.containsKey("003"));//false
System.out.println(map.size());//2
System.out.println(map.isEmpty());//false
map.clear();
System.out.println(map.size());//0
System.out.println(map.isEmpty());//true
System.out.println(map);//{}
}
5.3 Map集合的获取功能
方法名 | 说明 |
V get(Object key) | 根据键获取值 |
Set keySet() | 获取所有键的集合 |
Collection values() | 获取所有值的集合 |
Set<Map.Entry<K,V>> entrySet() | 获取所有键值对对象的集合 |
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","liubei");
map.put("002","guanyu");
map.put("003","zhangfei");
map.put("003","zhaoyun");
System.out.println(map.get("001"));//liubei
System.out.println(map.get("003"));//zhaoyun
System.out.println(map.get("000"));//null
Set<String> set = map.keySet();
for (String s : set){
System.out.print(s + " ");//001 002 003
}
System.out.println();
Collection<String> values = map.values();
for (String s : values){
System.out.print(s + " ");//liubei guanyu zhaoyun
}
}
5.4 Map集合的遍历(方式1)
- 我们在Map集合中存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合。遍历思路:
(1)把所有的丈夫给集中起来;
(2)遍历丈夫的集合,获取到每一个丈夫;
(3)根据丈夫去找对应的妻子。 - 转换为Map集合中的操作:
(1)获取所有键的集合。用keySet()方法实现;
(2)遍历键的集合,获取到每一个键。用增强for实现;
(3)根据键去找值,用get(Object key)实现。
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","liubei");
map.put("002","guanyu");
map.put("003","zhangfei");
map.put("003","zhaoyun");
Set<String> set = map.keySet();
for (String key : set){
System.out.println(key + "," + map.get(key));
}
}
5.5 Map集合的遍历(方式2)
- 我们在Map集合中存储的元素都是成对出现的,所以我们把Map看成是一个夫妻对的集合。遍历思路:
(1)获取所有的结婚证集合;
(2)遍历结婚证的集合,得到每一个结婚证;
(3)根据结婚证获取丈夫和妻子。 - 转换为Map集合中的操作:
(1)获取所有键值对对象的集合:Set<Map.Entry<K,V>> entrySet()。
(2)遍历键值对对象的集合,得到每一个键值对对象。用增强for实现,得到每一个Map.Entry。
(3)根据键值对对象获取键和值。用==getKey()得到键,用getValue()==得到值。
public static void main(String[] args) {
Map<String,String> map = new HashMap<>();
map.put("001","liubei");
map.put("002","guanyu");
map.put("003","zhangfei");
Set<Map.Entry<String, String>> entries = map.entrySet();
for (Map.Entry<String,String> entry : entries){
System.out.println(entry.getKey() + "," + entry.getValue());
}
}
案例:HashMap集合存储学生对象并遍历
- 需求:创建一个HashMap集合,键是学号(String),值是学生对象(Student)。存储三个键值对元素,并遍历。
- 思路:
(1)定义学生类;
(2)创建HashMap集合对象;
(3)创建学生对象;
(4)把学生添加到集合;
(5)遍历集合:根据键找值;根据键值对对象找键和值。
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Student{" +
"name='" + name + '\'' +
", age=" + age +
'}';
}
....................
public static void main(String[] args) {
HashMap<String,Student> hs = new HashMap<>();
Student s1 = new Student("liubei",12);
Student s2 = new Student("guanyu",22);
Student s3 = new Student("zhanfei",32);
hs.put("001",s1);
hs.put("002",s2);
hs.put("003",s3);
Set<String> set = hs.keySet();
for (String s : set){
System.out.println(s + "," + hs.get(s).getName() + "," + hs.get(s).getAge() + "");
}
Set<Map.Entry<String, Student>> entrySet = hs.entrySet();
for (Map.Entry<String,Student> entry : entrySet){
System.out.println(entry.getKey() + "," + entry.getValue().getName() + "," + entry.getValue().getAge());
}
}
案例:HashMap集合存储学生对象并遍历
- 需求:创建一个HashMap集合,键是学生对象(Student),值是居住地(String)。存储多个键值对元素,并遍历。要求保证键的唯一性:如果学生对象的成员变量相同,就认为是同一个对象。
- 思路:
(1)定义学生类;
(2)创建HashMap集合对象;
(3)创建学生对象;
(4)把学生添加到集合;
(5)遍历集合;
(6)在学生类中重写hashCode()和equals(),保证键的唯一性。
public class Student {
private String name;
private int age;
public Student() {
}
public Student(String name, int age) {
this.name = name;
this.age = 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;
if (age != student.age) return false;
return name != null ? name.equals(student.name) : student.name == null;
}
@Override
public int hashCode() {
int result = name != null ? name.hashCode() : 0;
result = 31 * result + age;
return result;
}
public static void main(String[] args) {
HashMap<Student,String> hs = new HashMap<>();
Student s1 = new Student("liubei",11);
Student s2 = new Student("guanyu",21);
Student s3 = new Student("zhanfei",31);
Student s4 = new Student("zhanfei",31);
hs.put(s1,"luoyang");
hs.put(s2,"jingzhou");
hs.put(s3,"xvchang");
hs.put(s4,"sichuang");//如果没有重写两个方法,就会输出两个zhanfei的项目
Set<Map.Entry<Student, String>> entrySet = hs.entrySet();
for (Map.Entry<Student, String> entry : entrySet){
System.out.println(entry.getKey().getName() + "," + entry.getKey().getAge() + "," + entry.getValue());
}
}
案例:ArrayList集合存储HashMap元素并遍历
- 创建一个ArrayList集合,存储三个元素,每一个元素都是HashMap,每一个HashMap的键和值都是String,并遍历。
- 思路:
(1)创建ArrayList集合;
(2)创建HashMap集合,并添加键值对元素;
(3)把HashMap作为元素添加到ArrayList集合;
(4)遍历ArrayList集合。
public static void main(String[] args) {
ArrayList<HashMap<String,String>> arrayList = new ArrayList<>();
HashMap<String, String> hm1 = new HashMap<>();
hm1.put("liubei","12");
hm1.put("guanyu","13");
arrayList.add(hm1);
HashMap<String, String> hm2 = new HashMap<>();
hm2.put("zhangfei","14");
hm2.put("zhugeliang","15");
arrayList.add(hm2);
HashMap<String, String> hm3 = new HashMap<>();
hm3.put("caocao","16");
hm3.put("caopi","17");
arrayList.add(hm3);
for (HashMap<String, String> hm : arrayList){
Set<String> set = hm.keySet();
for (String key : set){
System.out.println(key + "," + hm.values());
}
}
for (HashMap<String,String> hm : arrayList){
Set<Map.Entry<String, String>> entrySet = hm.entrySet();
for (Map.Entry<String,String> entry: entrySet){
System.out.println(entry.getKey() + "," + entry.getValue());
}
}
}
案例:HashMap集合存储ArrayList元素并遍历
- 创建一个HashMap集合,存储三个键值对元素,每一个键值对元素的键是String,值是ArrayList,每一个ArrayList的元素是String,并遍历。
- 思路:
(1)创建HashMap集合;
(2)创建ArrayList集合,并添加元素;
(3)把ArrayList作为元素添加到HashMap集合;
(4)遍历HashMap集合。
public static void main(String[] args) {
HashMap<String,ArrayList<String>> hm = new HashMap<>();
ArrayList<String> arrayList1 = new ArrayList<>();
arrayList1.add("liubei");
arrayList1.add("guanyu");
hm.put("蜀国",arrayList1);
ArrayList<String> arrayList2 = new ArrayList<>();
arrayList2.add("caocao");
arrayList2.add("caopi");
hm.put("魏国",arrayList2);
ArrayList<String> arrayList3 = new ArrayList<>();
arrayList3.add("sunquan");
arrayList3.add("sunce");
hm.put("吴国",arrayList3);
Set<String> set = hm.keySet();
for (String key: set){
System.out.print(key + ":");
for (String s : hm.get(key)){
System.out.print(s + " ");
}
System.out.println();
}
Set<Map.Entry<String, ArrayList<String>>> entrySet = hm.entrySet();
for (Map.Entry<String,ArrayList<String>> entry : entrySet){
System.out.print(entry.getKey() + ":");
for (String s : entry.getValue()){
System.out.print(s);
}
System.out.println();
}
}
案例:统计字符串中每个字符出现的个数
- 需求:键盘录入一个字符串,要求统计字符串中每个字符串出现的次数。
举例:键盘录入“aababcabcdabcde”,在控制台输出:“a(5)b(4)c(3)d(2)e(1)”。 - 分析:
(1)我们可以把结果分成几个部分来看:a(5),b(4),c(3),d(2),e(1);
(2)每一个部分可以看成是:字符和对应的次数组成;
(3)这样的数据,我们就可以通过HashMap集合来存储,键是字符,值是字符出现的次数;
(4)要注意的是,键是字符,类型应该是Character;值是字符出现的次数,类型应该是Integer。 - 思路:
(1)键盘录入一个字符串;
(2)创建HashMap集合,键是Character,值是Integer;
(3)遍历字符串,得到每一个字符;
(4)拿得到的每一个字符作为键到HashMap集合中去找对应的值,看其返回值。如果返回值是null,说明该字符在HashMap集合中不存在,就把该字符作为键,1作为值存储。如果返回值不是null,说明该字符在HashMap集合中存在,把该值加1,然后重新存储该字符串和对应的值;
(5)遍历HashMap集合,得到键和值,按照要求进行拼接;
(6)输出结果。
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入字符串:");
String s = sc.nextLine();
TreeMap<Character,Integer> hm = new TreeMap<>();
for (int i = 0; i<s.length();i++){
char key = s.charAt(i);
if (hm.get(key) == null){
hm.put(key,1);//自动装箱
}else {
hm.put(key,hm.get(key) + 1);
}
}
Set<Character> keySet = hm.keySet();
for (Character key : keySet){
System.out.print(key + "(" + hm.get(key) + ")");
}
}
面试题:HashMap和Hashtable的区别?
- HashMap不能保证元素的顺序,HashMap能够将键设为null,野结衣将值设为null。
- Hashtable不能将键和值设为null,否则运行时会报空指针异常。
- HashMap线程不安全,Hashtable线程安全。