1、Map集合介绍

1.1、Map集合的特点

在学习数组时,我们说如果和数组角标有一定的对应关系,是可以把数据存放在数组中,通过数组的角标来获取对应的数据,把这种方式称为查表法

可是当我们的对象与对象之间有了对应的关系,我们需要把这样具有对应关系的一对数据存放起来怎么做呢?采用数组只能存放具有简单对应关系的数据,不太合适。采用Collection集合,可是只能存放一个对象,无法维护这种关系。怎么做呢?

Java中我们提供了相应的其他容器来解决,这个容器就是Map集合。将键映射到值的对象一个映射不能包含重复的键每个键最多只能映射到一个值

例:

public class MapDemo {
	public static void main(String[] args){
		//创建Map对象
		Map<String,String> map = new HashMap<String,String>();
		//给map中添加元素
		map.put("星期一", "Monday");
		map.put("星期日", "Sunday");
		//当给Map中添加元素,会返回key对应的原来的value值,若key没有对象的值,返回null
		System.out.println(map.put("星期一", "M"));	
		
		/根据指定的key获取对应的value
		String en = map.get("星期日");
		System.out.println(en);
		
		//根据key删除元素,会返回key对应的value值
		String value = map.remove("星期日");
		System.out.println(value);
	}
}

2、Map集合中的方法

2.1、keySet方法

由于Map中的所有key都是不重复的,所以获取到Map中的所有key应该会存放在Set集合中,这个方法叫:keySet

public class MapDemo {
	public static void main(String[] args){
		// 创建集合
		Map<String,String> map = new HsahMap<String,String>();
		// 添加元素
		map.put("星期一","Monday");
		map.put("星期日", "Stringunday");
		//获取Map中的所有key
		Set<String> set = map.keySet();
		//遍历存放所有key的Set集合
		Iterator<String> it = keySet.iterator();
		while(it.hasNext()){
			String key = it.next();
			String value = map.get(key);
			System.out.println(key+"="+value);
		}
	}
}

2.2、entrySet方法

这个方法的描述是得到所有key和value的映射关系,这是啥意思呢?假设Map中存放一对一对的夫妻,那么entrySet获取到是每一对夫妻这种夫妻关系。

public class MapDemo {
	public static void main(String[] args) {
		//创建Map对象
		Map<String, String> map = new HashMap<String,String>();
		//给map中添加元素
		map.put("星期一", "Monday");
		map.put("星期日", "Sunday");
		//获取Map中的所有key与value的对应关系
		Set<Entry<String,string>> entry = map.entrySet();
		//遍历集合
		Iterator<Entry<String,String>> it = entry.iterator();
		 while(it.hasNext()){
		 	//得到每一对对应关系
		 	Entry<String,String> entry = it.next();
		 	//通过每一对对应关系获取对应的key
		 	String key = entry.getKey();
		 	//通过每一对对应关系获取对应的value
		 	String value = entry.getValue();
		 	System.out.println(key+"="+value);

注意:Map集合不能直接使用迭代器或者foreach进行遍历。但是转成Set之后就可以使用了。

3、Map集合常用子类介绍

3.1、Map常见子类的特点

Map有多个子类,这里我们主要讲解常用的HashMap和TreeMap集合;

HashMap:数据结构-哈希表。不是同步的,允许null作为键和值。HashMap下有个子类LinkedHashMap基于链表+哈希表。可以保证map集合有序(存入和取出的顺序一致)。

TreeMap:数据结构-二叉树。不是同步的。可以对map集合中的键进行排序。

3.2、HashMap存储自定义键值

练习:学生对象(姓名,年龄)都有自己的归属地

public class HashMapTest {
	public static void main(String[] args) {
		
		//1,创建hashmap集合对象。
		Map<Student,String> map = new HashMap<Student,String>();
		
		//2,添加元素。
		map.put(new Student("lisi",28), "上海");
		map.put(new Student("wangwu",22), "北京");
		map.put(new Student("zhaoliu",24), "成都");
		map.put(new Student("zhouqi",25), "广州");
		map.put(new Student("wangwu",22), "南京");

		//3,取出元素。keySet  entrySet
		//Set<Student> keySet = map.keySet();
		//for(Student key : keySet){}
		for(Student key : map.keySet()){
			String value = map.get(key);
			System.out.println(key.toString()+"....."+value);
		}

注意:当给HashMap中存放自定义对象时,如果自定义对象作为key存在,这时要保证对象唯一,必须复写对象的hashCodeequals方法

3.3、TreeMap存储自定义键值

练习:按照学生的年龄进行从小到大的排序。 TreeMap。

public class TreeMapTest {
	public static void main(String[] args) {
		// 1,创建TreeMap集合对象。
		Map<Student, String> map = new TreeMap<Student, String>();
		// 2,添加元素。
		map.put(new Student("lisi", 28), "上海");
		map.put(new Student("wangwu", 22), "北京");
		map.put(new Student("zhaoliu", 24), "成都");
		map.put(new Student("zhouqi", 25), "广州");
		map.put(new Student("wangwu", 22), "南京");
		//3,取出所有元素,entrySet()
		for(Map.Entry<Student,String> me : map.entrySet()){
			Student key = me.getkey();
			String value = me.getvalue();
			System.out.println(key+"::"+value);
		}

给TreeMap存放自定义对象,自定义对象作为key进行排序时,自定义对象必须具备比较功能,即实现Comparable接口。如果需要特定方式进行比较,我们也可以给TreeMap集合传递自定义的比较器进行比较。

3.4、Map练习-字母出现次数

获取字符串中每一个字母出现的次数。要求返回结果个格式是 a(1)b(2)d(4)…;

public class Maptext{
	public static void main(String[] args) {
		String str = "awaa+acr=ebarct,btydui[efgkiryuiop";
		str = getCharCount(str);
		System.out.println(str);
	}
	//获取字符串中的字母出现次数。
	public static String getCharCount(String str){
		//1.字符串转数组
		char[] chs = str.toCharArray();
		//2.定义表
		TreeMap<Character,Integer> map = new TreeMap<Character,Integer>();
		//3.遍历字符数组
		for(int i = 0;i<chs.length;i++){
			if(!(chs[i] >= 'a' && chs[i]<='z' || chs[i]>='A' && chs[i]<='Z')){
				continue;
			}
			//4,将遍历到的字母作为键去查map这个表。获取对应的次数。
			Integer value = map.get(chs[i]);
			//5,有可能要查询的字母在表中不存在对应的次数,需要判断。
			//如果返回是null,说明字母没有对应的次数。就将这个字母和1存储到表中。
			if(value == null){
				//将字母和1存储。
				map.put(chs[i],1);
			}else{
				value++;
				map.put(chs[i],value);
			}
		}
		return mapToString(map);
 	}
 	/*
	 * 将map集合中的键值转成   格式是  a(1)b(2)d(4)......
	 * map中有很多数据,无论是多少个,什么类型,最终都变成字符串。
	 * StringBuffer 这个容器就符合这个需求。如果是单线程,建议使用StringBuilder。
	 * 
	 */
	 private static String mapToString(Map<Character,Integer> map){
		//1,明确容器。
		StringBuilder sb = new StringBuilder();
		//2.遍历map集合
		for(Character key : map.keySet()){
			Integer value = map.get(key);
			sb.append(key+"("+value+")");
		}
		return sb.toString();
	}
}