Map集合的学习

在java中,除了Collection集合,还有一种集合叫做Map的集合。

Map也是一个接口,它的定义是:Map<K,V>,K,V是定义的泛型,K代表键,V代表值,Map的存放是以键值对的形式存放的,每一个键对应一个值,键就相当于数组的索引,只是键的类型是随意的,这也是Map集合最大的特点

在Map接口下有三个具体的实现:Hashtable,HashMap,TreeMap

Hashtable:底层数据类型是hash表(类似于HashSet),不能用null作为键或值,并且线程是同步的

HashMap:是Hashtable的升级版,区别在于HashMap可以用null作为键或值,线程是不同步的,其他与Hashtable一致

TreeMap:底层数据结构是二叉树,会对Map集合中的键进行排序,自定义排序方法类比TreeSet


==============================================================================================================================

Map中的方法:

1,添加:

V  put(K key,V value)//若传入的参数key已被使用,那么value将覆盖原有的值,并且函数最终返回原有的值,否则函数返回null


putAll(Map<? extends K,? extends V>m)//添加一个集合


2,删除:

clear()//清空集合


V remove(K key)//删除键key及其值,返回其值,如果key不存在,返回null


3,判断:

containsValue(V value)//判断有没有该值


containsKey(K key)//判断有没有该键


isEmpty()//判断有没有内容


4,获取:

get(K key)//获取key对应的值,若不存在,返回null


size()//返回集合长度


Collection values()//Map集合中所有值存放到一个Collection集合中


entrySet方式获取//下面讲


keySet方式获取//下面讲


给个例子:

//实现录入学号
import java.util.*;
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<String,String> map=new HashMap<String,String>();
		map.put("01","aaa");
		map.put("02","bbb");
		map.put("03","ccc");
		map.put("04","ddd");
		sop("02:"+map.containsKey("02"));
		sop("eee:"+map.containsValue("eee"));
		sop("01:"+map.get("01"));
		map.remove("01");
		sop("01:"+map.get("01"));
	}
}
/*结果
02:true
eee:false
01:aaa
01:null
*/


=============================================================================================================================

由于Map集合没有调用迭代器的方法,因此要把Map集合的内容存到Set集合中,在利用Set集合的迭代器来获取Map集合中元素,keySet和entrySet就是这种原理


keySet方式获取值:

Set<K> s=map.keySet()//把Map集合中的所有键存入到一个Set集合中,再通过Set集合的迭代器获取内容(就是存入的键),再通过get函数获取值

修改上述例子:

import java.util.*;
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<String,String> map=new HashMap<String,String>();
		map.put("01","aaa");
		map.put("02","bbb");
		map.put("03","ccc");
		map.put("04","ddd");
		Set<String> set=map.keySet();
		Iterator<String> it=set.iterator();
		while(it.hasNext())
		{
			String s=it.next();
			sop(s+":"+map.get(s));
		}
	}
}
/*结果
04:ddd
01:aaa
02:bbb
03:ccc
因为底层是hash表,乱序是正常的
*/


entrySet方法获取值:

Set<Map.Entry<K,V>> s=map.entrySet()//把Map集合中的映射关系存放到Set集合中,说到这就要介绍一下Map.Entry<K,V>,这是一个Map内部静态接口,用来记录键值关系,并且该接口提供了两个重要的功能:

getKey()//获得该映射的键

getValue()//获得该映射的值

那么,把映射放入Set集合后,通过Set集合的迭代器再加上getKey,getValue方法获取内容

继续修改上述例子:

import java.util.*;
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<String,String> map=new HashMap<String,String>();
		map.put("01","aaa");
		map.put("02","bbb");
		map.put("03","ccc");
		map.put("04","ddd");
		Set<Map.Entry<String,String>> set=map.entrySet();
		Iterator<Map.Entry<String,String>> it=set.iterator();
		while(it.hasNext())
		{
			Map.Entry<String,String> m=it.next();
			sop(m.getKey()+":"+m.getValue());
		}
	}
}
/*结果
04:ddd
01:aaa
02:bbb
03:ccc
因为底层是hash表,乱序是正常的
*/


=============================================================================================================================

因为hashSet和hashtable底层是hash表,所以当用自定义类对象来当键时,由于键是唯一的,为了确保键的唯一性,需要在自定义类中要重写hashCode和equals方法,具体原理可参考hashSet集合


实例解释:

//需要建立一些学生对象,每个学生都对应着居住地,名字和年龄相同的为同一个学生
import java.util.*;
class Student
{
	public int age;
	public String name;
	public Student(String name,int age)
	{
		this.age=age;
		this.name=name;
	}
	public int hashCode()//根据名字年龄生成hash值
	{
		return name.hashCode()+age;
	}
	public boolean equals(Object s)
	{
		if(!(s instanceof Student))
			throw new RuntimeException();
		Student p=(Student)s;
		if(this.age==p.age)
		{
			return this.name.equals(p.name);
		}
		return false;
	}
}
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<Student,String> map=new HashMap<Student,String>();
		map.put(new Student("zhangsan",12),"CHN");		
		map.put(new Student("zhangsan",12),"USA");
		map.put(new Student("lisi",12),"USA");
		map.put(new Student("zhangsan",15),"CHN");
		Set<Map.Entry<Student,String>> set=map.entrySet();
		Iterator<Map.Entry<Student,String>> it=set.iterator();
		while(it.hasNext())
		{
			Map.Entry<Student,String> m=it.next();
			Student s=m.getKey();
			sop(s.name+"..."+s.age+":"+m.getValue());
		}
	}
}
/*结果
zhangsan...15:CHN
zhangsan...12:USA
lisi...12:USA
因为底层是hash表,乱序是正常的
之所以接收的12岁zhangsan来自USA是因为相同键的情况下后接收的值会覆盖先前的值
*/


同理,TreeMap在使用自定义类对象作为键时,也要自定义一个比较器或者自定义类实现Comparable,具体原理可参照TreeSet


对上述例子进行修改:

1,实现Comparable方式:

//需要建立一些学生对象,每个学生都对应着居住地,名字和年龄相同的为同一个学生
import java.util.*;
class Student implements Comparable<Student>//该接口使用了泛型,不明白就查阅API文档
{
	public int age;
	public String name;
	public Student(String name,int age)
	{
		this.age=age;
		this.name=name;
	}
	public int compareTo(Student s)
	{
		int num=this.age-s.age;
		if(num==0)
		{
			return this.name.compareTo(s.name);
		}
		return num;
	}
}
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<Student,String> map=new TreeMap<Student,String>();
		map.put(new Student("zhangsan",12),"CHN");		
		map.put(new Student("zhangsan",12),"USA");
		map.put(new Student("lisi",12),"USA");
		map.put(new Student("zhangsan",15),"CHN");
		Set<Map.Entry<Student,String>> set=map.entrySet();
		Iterator<Map.Entry<Student,String>> it=set.iterator();
		while(it.hasNext())
		{
			Map.Entry<Student,String> m=it.next();
			Student s=m.getKey();
			sop(s.name+"..."+s.age+":"+m.getValue());
		}
	}
}
/*结果
lisi...12:USA
zhangsan...12:USA
zhangsan...15:CHN
不仅正确接收内容(无重复),还根据自定义规则排序
*/


2,自定义比较器方式:

//需要建立一些学生对象,每个学生都对应着居住地,名字和年龄相同的为同一个学生
import java.util.*;
class MyComparator implements Comparator<Student>
{
	public int compare(Student s1,Student s2)
	{
		int num=s1.age-s2.age;
		if(num==0)
		{
			return s1.name.compareTo(s2.name);
		}
		return num;
	}
}
class Student
{
	public int age;
	public String name;
	public Student(String name,int age)
	{
		this.age=age;
		this.name=name;
	}
}
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<Student,String> map=new TreeMap<Student,String>(new MyComparator());//加入比较器
		map.put(new Student("zhangsan",12),"CHN");		
		map.put(new Student("zhangsan",12),"USA");
		map.put(new Student("lisi",12),"USA");
		map.put(new Student("zhangsan",15),"CHN");
		Set<Map.Entry<Student,String>> set=map.entrySet();
		Iterator<Map.Entry<Student,String>> it=set.iterator();
		while(it.hasNext())
		{
			Map.Entry<Student,String> m=it.next();
			Student s=m.getKey();
			sop(s.name+"..."+s.age+":"+m.getValue());
		}
	}
}
/*结果
lisi...12:USA
zhangsan...12:USA
zhangsan...15:CHN
效果完全一样
*/


=============================================================================================================================

最后讲一下多重映射关系,比如说在学校这个容器里,每个班都有自己的编号,而每个班又可以看做一个容器,其中的每个同学都有自己在班中的学号,这就出现了多重映射关系,在编程中就会出现容器中包含容器的情况


以上述例子说明:

import java.util.*;
class Student
{
	public int age;
	public String name;
	public Student(String name,int age)
	{
		this.age=age;
		this.name=name;
	}
}
class MapDemo 
{
	public static void sop(Object obj)
	{
		System.out.println(obj);
	}
	public static void main(String[] args) 
	{
		Map<Integer,Map<String,Student>> school=new HashMap<Integer,Map<String,Student>>();//建立学校
		Map<String,Student> classroom1=new HashMap<String,Student>();//建立教室
		Map<String,Student> classroom2=new HashMap<String,Student>();
		school.put(1,classroom1);//把教室加入学校容器,因为容器存的是对象的引用,所以先存教室再存学生和先存学生再存教室一样
		school.put(2,classroom2);
		classroom1.put("01",new Student("zhangsan",12));//把学生存入相应的教室
		classroom1.put("02",new Student("lisi",15));
		classroom1.put("03",new Student("wangwu",13));
		classroom2.put("01",new Student("zhangsan",12));
		classroom2.put("02",new Student("zhaoliu",12));
		classroom2.put("03",new Student("lisi",17));
		Set<Map.Entry<Integer,Map<String,Student>>> ss=school.entrySet();
		Iterator<Map.Entry<Integer,Map<String,Student>>> s_it=ss.iterator();//用于遍历学校容器
		while(s_it.hasNext())
		{
			Map.Entry<Integer,Map<String,Student>> m=s_it.next();
			sop("classroom "+m.getKey()+":");
			Set<Map.Entry<String,Student>> c=m.getValue().entrySet();
			Iterator<Map.Entry<String,Student>> c_it=c.iterator();//用于遍历教室容器
			while(c_it.hasNext())
			{
				Map.Entry<String,Student> c_m=c_it.next();
				sop(c_m.getKey()+" : "+c_m.getValue().name+"..."+c_m.getValue().age);
			}
		}
	}
}
/*结果
classroom 1:
01 : zhangsan...12
02 : lisi...15
03 : wangwu...13
classroom 2:
01 : zhangsan...12
02 : zhaoliu...12
03 : lisi...17
*/

用entrySet方法真是够酸爽!!!!
























评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值