1. Map概述
Map集合特点:该集合存储键值对。一对一对往里面存,而且要保证键的唯一性。
- Hashtable
- HashMap
- TreeMap
添加 put(key, value); putAll(Map<? extends K, ? extends V>)
删除 clear(); remove(Onject key)
判断 containsKey(Object key); containsValue(Object value);
获取 get(Object key); size(); value(); entrySet(); keySet();
2. Map子类对象特点
Hashtable: 底层是哈希表数据结构,不可以存入null键、null值,该集合是同步的,jdk1.0,效率低
HashMap: 底层是哈希表数据结构,允许存入null键、null值,该集合是不同步的,jdk1.2,效率高
TreeMap: 底层是二叉树数据结构,线程不同步,可以给map集合中的键进行排序
Map和Set很像,其实Set底层就是使用了Map集合。
3.
添加元素: 如果出现添加相同的键,那么后添加的值会覆盖原有键对应的值,并put方法会返回被覆盖的值。
package Map;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
//添加元素
map.put("01","gy");
map.put("02","gy");
map.put("03","gy");
System.out.println("containsKey:"+map.containsKey("01"));
System.out.println("remove:"+map.remove("01"));
map.put("02","gy1");
System.out.println("get:"+map.get("02"));
// 可以通过get方法的返回值来判断一个键是否存在,通过返回null来判断
//获取Map中所有的值
Collection<String> coll = map.values();
System.out.println(coll);
}
}
4. Map-keySet
Map集合的这两种取出方式:
第一种方式: Set<k> keySet():返回此映射中包含的键的Set视图
,将Map中所有的键存入到Set集合中,因为Set具备迭代器,所以可以使用迭代的方式取出所有的键,再根据get方法,获取每一个键对应的值。
Map集合取出原理:将Map集合转成Set集合,再通过迭代器取出。
package Map;
import java.util.*;
public class MapDemo2 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("01","gy1");
map.put("03","gy3");
map.put("02","gy2");
//先获取map集合的所有键的Set集合,keySet()
Set<String> keySet = map.keySet();
Iterator<String> it = keySet.iterator();
while (it.hasNext()){
String s = it.next(); //获取key
System.out.println("key:"+s+"...value:"+map.get(s));
}
}
}
输出结果:
key:01...value:gy1
key:02...value:gy2
key:03...value:gy3
5. Map-entrySet
第二种方式: Set<Map.Entry<K, V>> entrySet():返回此映射中包含的映射关系的Set视图。
而这个关系的数据类型就是:Map.Entry
关系对象Map.Entry
获取到后,就可以通过Map.Entry
中的getKey()
和getValue()
获取到关系中的键和值
package Map;
import java.util.*;
public class MapDemo2 {
public static void main(String[] args) {
Map<String, String> map = new HashMap<String, String>();
map.put("01","gy1");
map.put("03","gy3");
map.put("02","gy2");
//将Map集合中的映射关系取出,存入到Set集合中
Set<Map.Entry<String,String>> entrySet = map.entrySet();
Iterator<Map.Entry<String,String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<String,String> me = it.next(); //获取key
System.out.println("key:"+me.getKey()+"...value:"+me.getValue());
}
}
}
结果:
key:01...value:gy1
key:02...value:gy2
key:03...value:gy3
Map.Entry
其实Entry
也是一个接口,它是Map
接口中的一个内部接口。
interface Map{
public static interface Entry{
public abstract Object getKey();
public abstract Object getValue();
}
}
class HashMap implements Map{
class Haha implements Map.Entry{
public Object getKey(){}
public Object getValue(){}
}
}
6. Map练习题
题目: 每一个学生都有对应的归属地。
学生Student, 地址String
学生属性:姓名、年龄。
注意:姓名和年龄相同视为同一个学生。保证学生的唯一性。
- 描述学生
- 定义Map容器,将学生作为键,地址作为值,存入
- 获取Map集合中的内容
package Map;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
class Student{
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public String getName() {
return name;
}
public int getAge() {
return age;
}
public void setName(String name) {
this.name = name;
}
public void setAge(int age) {
this.age = age;
}
public String toString(){
return "("+name+","+age+")";
}
public int hashCode(){
return name.hashCode()+age*10;
}
public boolean equals(Object obj){
if(obj instanceof Student){
Student s = (Student)obj;
return this.name.equals(s.name) && this.age == s.age;
}
throw new ClassCastException("类型不匹配");
}
}
public class MapTest {
public static void main(String[] args) {
Map<Student, String> map = new HashMap<Student, String>();
map.put(new Student("shh1",1),"Wuhan");
map.put(new Student("shh1",1),"Nanjing");
map.put(new Student("shh3",3),"Beijing");
// 第一种取出方式
System.out.println("第一种取出方式:");
Set<Student> ketSet = map.keySet();
Iterator<Student> it1 = ketSet.iterator();
while (it1.hasNext()){
Student stu = it1.next();
String addr = map.get(stu);
System.out.println(stu.toString()+" in "+addr);
}
//第二种取出方式
System.out.println("第二种取出方式:");
Set<Map.Entry<Student,String>> entrySet = map.entrySet();
Iterator<Map.Entry<Student,String>> it2 = entrySet.iterator();
while (it2.hasNext()){
Map.Entry<Student,String> me = it2.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu.toString()+" in "+addr);
}
}
}
输出结果:
第一种取出方式:
(shh3,3) in Beijing
(shh1,1) in Nanjing
第二种取出方式:
(shh3,3) in Beijing
(shh1,1) in Nanjing
7. TreeMap练习题
题目: 对学生对对象进行升序排序。按照姓名
因为数据是以键值对形式存在的。所以要使用可以排序的Map集合,TreeMap
package TreeMap;
import java.util.*;
class Student{
private String name;
private int age;
public Student(String name, int age){
this.name = name;
this.age = age;
}
public int getAge() {
return age;
}
public String getName() {
return name;
}
public void setAge(int age) {
this.age = age;
}
public void setName(String name) {
this.name = name;
}
public String toString(){
return "( name:"+name+", age:"+age+")";
}
}
class StuNameComparator implements Comparator<Student> {
public int compare(Student s1, Student s2){
int num = s1.getName().compareTo(s2.getName());
if(num == 0) return s1.getAge() - s2.getAge();
return num;
}
}
public class TreeMapTest {
public static void main(String[] args) {
Map<Student, String> treeMap = new TreeMap<Student, String>(new StuNameComparator());
treeMap.put(new Student("shh1",10),"Wuhan");
treeMap.put(new Student("shh3",3),"Nanjing");
treeMap.put(new Student("shh2",12),"Beijing");
treeMap.put(new Student("shh2",12),"Shanghai");
Set<Map.Entry<Student, String>> entrySet = treeMap.entrySet();
Iterator<Map.Entry<Student, String>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<Student, String> me = it.next();
Student stu = me.getKey();
String addr = me.getValue();
System.out.println(stu.toString()+" in "+addr);
}
}
}
输出结果:
( name:shh1, age:10) in Wuhan
( name:shh2, age:12) in Shanghai
( name:shh3, age:3) in Nanjing
8. 字母出现的次数
题目: “sdfgdhaodygvguaschf” 获取该字符串中字母出现的次数。希望打印的结果:a(2) c(1)…
分析: 通过结果发现,每一个字母都有对应的次数。说明字母和数字之间有映射关系。
注意了,当发现具有映射关系,可以使用Map集合,因为Map集合中存放就是映射关系。
什么时候使用Map集合? 当数据之间存在这重映射关系时,就要先想到Map集合。
思路:
- 将字符串转化成字符数组,因为要对每一个字符进行操作
- 定义一个Map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。
- 遍历字符数组。将每一个字母作为键去查Map集合,如果返回null,将该字母和1存入Map集合中;如果返回的不是null,说明该字母在Map集合中已经存在,那么就获取该字母对应的次数,并进行自增,然后将该字母和自增后的次数存入到Map集合中,覆盖原来键对应的值。
- 将Map集合中的数据变成指定的字符串形式返回
package TreeMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapTest2 {
public static void main(String[] args) {
Map<Character, Integer> map = statsNum("sdfgdhaodygvguaschf");
Set<Map.Entry<Character,Integer>> entrySet = map.entrySet();
Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
while (it.hasNext()){
Map.Entry<Character,Integer> me = it.next();
char c = me.getKey();
int count = me.getValue();
System.out.println(c+"("+count+")");
}
}
public static Map<Character,Integer> statsNum(String s){
Map<Character,Integer> map = new TreeMap<>(); // 注意:泛型里面的存的都是对象,所以不能使用char和int
char[] strs = s.toCharArray();
int len = s.length();
char c;
for(int i=0; i<len; i++){
c = strs[i];
if(map.get(c) == null){
map.put(c,1);
}
else{
int count = map.get(c);
count++;
map.put(c,count);
}
}
return map;
}
}
输出结果:
a(2) c(1) d(3) f(2) g(3) h(2) o(1) s(2) u(1) v(1) y(1)
9. Map集合的扩展
Map集合被使用是因为具备映射关系。
“Wuhan” "01" "shh01"
“Wuhan” "02" "shh02"
“Nanjing” "01" "gy01"
“Nanjing” "01" "gy02"
package Map;
import java.util.*;
public class MapDemo {
public static void main(String[] args) {
Map<String, Map<String, String>> residence = new HashMap<>();
Map<String, String> people1 = new HashMap<String, String>();
Map<String, String> people2 = new HashMap<String, String>();
people1.put("01","shh1");
people1.put("02","shh2");
people2.put("01","gy1");
people2.put("02","gy2");
residence.put("Wuhan",people1);
residence.put("Nanjing",people2);
System.out.println("_______________1_______________");
getPeopleInfo(people1);
System.out.println("_______________2_______________");
getPeopleInfo(people2);
//遍历residence集合,获取所有的城市
System.out.println("_______________3_______________");
Iterator<String> it = residence.keySet().iterator();
while (it.hasNext()){
String city = it.next();
System.out.println(city);
Map<String, String> people = residence.get(city);
getPeopleInfo(people);
}
}
public static void getPeopleInfo(Map<String, String> cityMap){
Set<String> keySet = cityMap.keySet();
Iterator<String> it = keySet.iterator();
while (it.hasNext()){
String id = it.next();
String name = cityMap.get(id);
System.out.println(id+":"+name);
}
}
}
输出:
_______________1_______________
01:shh1
02:shh2
_______________2_______________
01:gy1
02:gy2
_______________3_______________
Wuhan
01:shh1
02:shh2
Nanjing
01:gy1
02:gy2