一,Map集合的基本操作
package fighting;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
public class MapDemo {
/**
* Map:存储一组成对的键值对象,key不要求有序,但不能重复;value也不要求有序,但允许重复。
*
* Collection是单列集合,Map是双列集合。
*
* 1,添加
* put(k,v)
* pubAll()
* 2,删除
* clear()
* remove(k)
* 3,判断
* containsKey()
* containsValue()
* isEmpty()
* 4,获取
* get()
* size()
* values()
*
* entrySet()
* keySet()
*
* Map
* |-HashTable:底层是哈希表数据结构,不可以存入null键和null值,线程同步,效率低。
* 用作键的对象必须实现hashCode方法和equals方法。
* |-HashMap:底层是哈希表数据结构,允许使用null键和null值,该集合是不同步,效率高。
* |-TreeMap:底层是二叉树数据结构,线程不同步,可以用于给map集合中的键进行排序。
*
* TreeMap和Set很想,其实,Set底层就是使用了Map集合。
*/
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
//添加元素
map.put("01", "zhangsan001");
map.put("02", "zhangsan002");
map.put("03", "zhangsan003");
System.out.println("containsKey:"+map.containsKey("02"));//containsKey:true
//remove方法返回值:与 key 关联的旧值;如果 key 没有任何映射关系,则返回 null。(返回 null 还可能表示该映射之前将 null 与 key 关联。)
System.out.println("remove:"+map.remove("022"));//remove:null
System.out.println("remove:"+map.remove("02"));//remove:zhangsan002
//可以通过get方法的返回值来判断一个键是否存在。
System.out.println("get:"+map.get("02"));//get:null
System.out.println("get:"+map.get("03"));//get:zhangsan003
//下面这两种特殊情况
map.put(null, "aaa");
System.out.println("get:"+map.get(null));//get:aaa
map.put("04", null);
System.out.println("get:"+map.get("04"));//get:null
//这行代码说明,使用get方法获取的null为空,不能说明没有这个键,也可能是映射之前将null和key关联
//获取map集合中所有的值
Collection<String> coll = map.values();//这里不要Collection<V> coll,实际使用中,要把V变成具体的类型。
System.out.println(coll);//[zhangsan001, zhangsan003, null, aaa]
//注意:添加元素时,如果出现相同的key,后添加的值会覆盖原有的键对应的值,并且返回原来的这个值。
System.out.println(map.put("ch", "中国"));//null
System.out.println(map.put("ch", "中华人民共和国"));//中国
System.out.println(map);//{ch=中华人民共和国, 01=zhangsan001, 03=zhangsan003, 04=null, null=aaa}
}
}
二,Map集合的两种取出方式:
package fighting;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class MapKeySet {
/**
* map集合的两种取出方式:
* 1,keySet:将map集合中所有的键存入到Set集合,因为Set具备迭代器,
* 所以可以使用迭代方式取出所有的键,再根据get方法,获取每一个键对应的值
* map集合没有迭代器,map集合的取出原理:将map集合转成Set,利用Set的迭代器迭代取出。
* 2,entrySet:返回映射中包含的映射关系的Set视图--Map.Entry<K,V>
* Map.Entry 其实Entry也是一个接口,他是Map接口中的一个内部接口。
* interface Map
* {
* public static interface Entry{
* public abstract Object getKey();
* public abstract Object getValue();
* }
* }
* class HashMap implements implements Map{
*
* class xxx implements Map.Entry{
* public Object getKey(){};
* public Object getValue(){};
* }
* }
*/
public static void main(String[] args) {
Map<String,String> map=new HashMap<String,String>();
//添加元素
map.put("01", "zhangsan001");
map.put("02", "zhangsan002");
map.put("04", "zhangsan004");
map.put("03", "zhangsan003");
//获取map集合中所有键的Set集合
Set<String> keySet = map.keySet();
//获取迭代器
Iterator<String> it = keySet.iterator();
while(it.hasNext()){
String key = it.next();
System.out.println("key:"+key+" value:"+map.get(key));
}
/*输出结果
* key:01 value:zhangsan001
* key:03 value:zhangsan003
* key:04 value:zhangsan004
* key:02 value:zhangsan002
*/
Set<Map.Entry<String, String>> entryset = map.entrySet();
Iterator<Map.Entry<String, String>> it1 = entryset.iterator();
while(it1.hasNext()){
Map.Entry<String, String> me = it1.next();
String key = me.getKey();
String value = me.getValue();
System.out.println(key+":"+value);
}
/*输出结果
* 01:zhangsan001
* 03:zhangsan003
* 04:zhangsan004
* 02:zhangsan002
*/
}
}
三,有关Map的一个小练习:
package fighting;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import com.itheima.Student;
public class MapDemo2 {
/**
* 练习:每一个学生都有对应的归属地。
* 学生Student,地址String
* 学生属性:姓名,年龄
* 注意:姓名和年龄相同的视为同一个学生
* 保证学生的唯一性。
*
* 1,描述学生。
* 2,定义map容易,将学生作为键,地址作为值,存入。
* 3,获取map集合中的元素。
*
*/
public static void main(String[] args) {
HashMap<Student0627,String> hm = new HashMap<Student0627,String>();
hm.put(new Student0627("zhangsan001",22), "北京");
hm.put(new Student0627("zhangsan002",23), "河北");
hm.put(new Student0627("zhangsan003",24), "内蒙古");
hm.put(new Student0627("zhangsan004",25), "天津");
//第一种取出方式:keySet
Set<Student0627> keySet =hm.keySet();
Iterator<Student0627> it = keySet.iterator();
while(it.hasNext()){
Student0627 stu = it.next();
System.out.println(stu+hm.get(stu));
}
/*
* zhangsan001...22北京
* zhangsan004...25天津
* zhangsan003...24内蒙古
* zhangsan002...23河北
*/
//第二种取出方式:entrySet
Set<Map.Entry<Student0627, String>> entrySet = hm.entrySet();
Iterator<Map.Entry<Student0627, String>> it1 = entrySet.iterator();
while(it1.hasNext()){
Map.Entry<Student0627, String> me= it1.next();
System.out.println(me.getKey()+"..."+me.getValue());
}
/*
* zhangsan001...22...北京
*zhangsan004...25...天津
*zhangsan003...24...内蒙古
*zhangsan002...23...河北
*/
//再添加一条记录,key已经存在,值不同
hm.put(new Student0627("zhangsan001",22), "广东");
Set<Map.Entry<Student0627, String>> entrySet2 = hm.entrySet();
Iterator<Map.Entry<Student0627, String>> it2 = entrySet.iterator();
while(it2.hasNext()){
Map.Entry<Student0627, String> me= it2.next();
System.out.println(me.getKey()+"..."+me.getValue());
}
/*
* zhangsan001...22...广东 ----注意zhangsan001这一条归属地变成了"广东"
* zhangsan004...25...天津
* zhangsan003...24...内蒙古
* zhangsan002...23...河北
*/
}
}
//注意:类的对象不确定要存到什么集合中去,所以要保证保存到任何集合中都不会出错
//①要覆盖hashCode方法和equals方法,
//②还要实现Comparable接口,实现compareTo方法。
class Student0627 implements Comparable<Student0627>{
private String name;
private int age;
public Student0627(String name,int age){
this.name=name;
this.age=age;
}
public int compareTo(Student0627 o) {
int num = new Integer(this.age).compareTo(new Integer(o.age));
if(num==0)
return this.name.compareTo(o.name);
return num;
}
public int hashCode(){
return name.hashCode()+age*34;
}
public boolean equals(Object obj){
if(!(obj instanceof Student0627)){
throw new ClassCastException("类型不匹配");
}
Student0627 s =(Student0627)obj;
return this.name.equals(s.name)&&this.age==s.age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
@Override
public String toString(){
return this.name+"..."+this.age;
}
}
四,上一个小练习(MapDemo2)的需求升级:
package fighting;
import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo {
/**
* MapDemo2的续:
* 需求:对学生对象的年龄进行升序排序。
* 需求2:按照学生对象的姓名升序排序
* 因为数据是以键值对形式存在的,所以要使用可以排序的Map集合--TreeMap
*
*/
public static void main(String[] args) {
//需求1
TreeMap<Student0627,String> tm = new TreeMap<Student0627,String>();
tm.put(new Student0627("bzhangsan003",23), "北京");
tm.put(new Student0627("zhangsan001",21), "河北");
tm.put(new Student0627("azhangsan004",24), "内蒙古");
tm.put(new Student0627("zhangsan002",22), "天津");
Set<Map.Entry<Student0627,String>> entrySet =tm.entrySet();
Iterator<Map.Entry<Student0627,String>> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry<Student0627,String> me =it.next();
Student0627 stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"..."+addr);
}
/*
* zhangsan001...21...河北
* zhangsan002...22...天津
* bzhangsan003...23...北京
* azhangsan004...24...内蒙古
*/
//需求2:如果想按照姓名升序进行排序,可以自定义比较器,传入TreeMap构造方法
TreeMap<Student0627,String> tm2 = new TreeMap<Student0627,String>(new StuNameComparator());
tm2.put(new Student0627("bzhangsan003",23), "北京");
tm2.put(new Student0627("zhangsan001",21), "河北");
tm2.put(new Student0627("azhangsan004",24), "内蒙古");
tm2.put(new Student0627("zhangsan002",22), "天津");
Set<Map.Entry<Student0627,String>> entrySet2 =tm2.entrySet();
Iterator<Map.Entry<Student0627,String>> it2 = entrySet2.iterator();
while(it2.hasNext()){
Map.Entry<Student0627,String> me =it2.next();
Student0627 stu = me.getKey();
String addr = me.getValue();
System.out.println(stu+"..."+addr);
}
/*
* azhangsan004...24...内蒙古
* bzhangsan003...23...北京
* zhangsan001...21...河北
* zhangsan002...22...天津
*/
}
}
class StuNameComparator implements Comparator<Student0627>{
public int compare(Student0627 s1, Student0627 s2) {
int num =s1.getName().compareTo(s2.getName());
if(num==0){
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}
五,有关Map的第二个小练习--字母出现的次数:
package fighting;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapDemo1 {
/**
* 练习:
* "adsgljrgsgjfdgf"获取该字符串中的字母出现的次数。
* 希望打印结果:a(1)c(2)...
*
* 通过结果发现,每一个字母都有对应的次数,
* 说明字母和次数之间都有映射关系。
*
* 注意了,当发现有映射关系时,就可以选择Map集合,
* 因为Map集合中存放就是映射关系。
*
* 思路:
* 1,将字符串转换成字符数组,因为要对每一个字符进行操作。
* 2,定义一个map集合,因为打印结果的字母有顺序,所以使用TreeMap集合,
* 3,遍历字符数组,将每一个字母作为键,去查map集合,
* 如果返回null,就将该字母和1存入map集合;
* 如果返回不是null,说明该字母在map集合内已经存在,并有对应的次数,
* 那么就获取该次数并自增,让后让该字母和自增后的次数覆盖到集合中,覆盖到原来的键和对应的值
* 4,将Map集合的数据指定的字符串形式返回
*/
public static void main(String[] args) {
String str = carCount("adsgljrgsgjfdgf");
System.out.println(str);
}
public static String carCount(String str){
char[] chs = str.toCharArray();
TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();
int count=0;
for(int x=0;x<chs.length;x++){
if(chs[x]>='a'&&chs[x]<='z'||chs[x]>='A'&&chs[x]<='Z'){//非字母不用计算个数
continue;
}
Integer value = tm.get(chs[x]);
//方法二
if(value!=null){//不等于空,说明已经存在这个key,那么把key对应的值赋给count,再加一
count = value;
}
count++;
tm.put(chs[x], count);
count =0;
//方法一
/*if(value==null){
value = 1;
tm.put(chs[x], 1);
}else{
value++;
tm.put(chs[x], value);
}*/
}
StringBuilder sb = new StringBuilder();
Set<Map.Entry<Character,Integer>> entrySet = tm.entrySet();
Iterator<Map.Entry<Character,Integer>> it = entrySet.iterator();
while(it.hasNext()){
Map.Entry<Character,Integer> me= it.next();
Character ch = me.getKey();
Integer value = me.getValue();
sb.append(ch+"("+value+")");
}
return sb.toString();//把sb转换成字符串类型返回,这里toString不能省略
}
}
六,Map扩展知识:大集合嵌套小集合、一对多映射
package fighting;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
public class MapDemo1 {
/**
* Map扩展知识:
* map集合被使用是因为具备映射关系。。
*
* 需求:一个学校有多个班级,每个班级有多名学生,利用Map遍历所有学生
* 比如:学校有预热班和就业班
* "预热班","1号","张三"
* "预热班","2号","李四"
* "就业班","1号","张三"
* "就业班","2号","李四"
*
* 需求2:把学号和学生姓名封装成学生对象进行操作。
*
* 大集合里嵌套小集合
* 一对多映射
*/
public static void main(String[] args) {
//分别定义学校、预热班、就业班
HashMap<String,HashMap<String,String>> school = new HashMap<String,HashMap<String,String>>();
HashMap<String,String> yure=new HashMap<String,String>();
HashMap<String,String> jiuye =new HashMap<String,String>();
//把班级信息添加到学校集合
school.put("预热班", yure);
school.put("就业班", jiuye);
//把学生信息添加到班级集合
yure.put("1号", "张三");
yure.put("2号", "李四");
//把学生信息添加到班级集合
jiuye.put("1号", "张三er");
jiuye.put("2号", "李四er");
//遍历输出,
Iterator<String> it = school.keySet().iterator();//获取学校的所有班级信息
while(it.hasNext()){
String roomName = it.next();//班级名称--预热班、就业班
HashMap<String,String> room = school.get(roomName);//班级对应的集合--yure、jiuye
Iterator<String> it1 = room.keySet().iterator();//班级里学生信息的学号集合
while(it1.hasNext()){
String id = it1.next();//学号
System.out.println(roomName+id+"::"+room.get(id));
}
}
System.out.println("---------------------------把学生封装成对象(Student27)实现如下--------------------------------");
demo();
}
public static void demo(){
//把学生信息保存到List集合里,就是说每一个班级对应一个学生的List集合,
//获取班级信息后,就可以获取学生的一个List集合,再迭代这个List集合就可以得到所有学生信息。
HashMap<String,List<Student27>> hm = new HashMap<String,List<Student27>>();
List<Student27> yure = new ArrayList<Student27>();
List<Student27> jiuye = new ArrayList<Student27>();
hm.put("预热班", yure);
hm.put("就业班", jiuye);
yure.add(new Student27("1号", "张三"));
yure.add(new Student27("2号", "李四"));
jiuye.add(new Student27("1号", "张三er"));
jiuye.add(new Student27("2号", "李四er"));
Iterator<String> it = hm.keySet().iterator();
while(it.hasNext()){
String roomName = it.next();
List<Student27> room = hm.get(roomName);
Iterator<Student27> it1 = room.iterator();
while(it1.hasNext()){
Student27 stu = it1.next();
System.out.println(roomName+stu.getId()+"::"+stu.getName());
}
}
}
}
//把学号和学生姓名封装成学生对象--学生类
class Student27 {
private String id;
private String name;
public Student27(String id,String name){
this.id=id;
this.name=name;
}
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;
}
}