Java基础17--Map

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xzm_rainbow/article/details/17892319

17-1,Map集合特点&常用方法

1,Map是一个接口,一次添加一对元素,Collection是一次添加一个元素。Map也成为双列集合,Collection集合称为单列集合。

2,Map<K,V>,是将键映射到值得对象。K-->Key,V-->Value,<K,V>即为键值对。

且一个映射当中不能包含重复的键,每个键最多只能映射到一个值上。也就是说,Map是一个键值对,Map集合中必须保证键的唯一性。

3,Map常用方法。

(1)添加:

value put(key,value):返回前一个与key关联的值,如果没有,则返回null。

比如,先保存了一对<k1,v1>,然后保存<k1,v2>,这时由于k1相同,则v2会覆盖v1,返回v1的值,保证了key的唯一性。

(2)删除:

void clear():清空

value remove(key):根据指定的key删除这个键值对,返回这个key对应的value。

(3)判断:

boolean containsKey(key):判断是否包含指定的key。

boolean containsValue(value):判断是否包含指定的value。

boolean isEmpty():判断是否为空。

(4)获取:

value get(key):通过key取出对应的value,如果不包含这个key,则返回null,可以通过返回null,来判断是否包含指定键。

int size():获取键值对的个数。

 

17-2,常用方法演示

public class Demo{
	public static void main(String[] args) {
		Map<Integer,String> map = new HashMap<Integer,String>();
		method(map);
	}
	public static void method(Map<Integer,String> map) {
		System.out.println(map.put(8,"wangcai"));//null
		System.out.println(map.put(8,"xiaoqiang"));//wangcai
		System.out.println(map);//{8-xiaoqiang}
		//删除
		System.out.println(map.remove(2));//根据key,删除<k,v>键值对,返回value
		//判断
		System.out.println(map.containsKey(8));
		//获取
		System.out.println(map.get(8));
	}
}

 

17-3,重点方法keySet()演示图解

1,Set<key> keyset():返回此映射中所包含的键的set视图。

2,演示:

public class Demo {
	public static void main(String[] args) {
		Map<Integer,String> map = new HashMap<Integer,String>();
		method(map);
	}
	public static void method(Map<Integer,String> map) {
		map.put(8,"zhaoliu");
		map.put(2,"wangwu");
		map.put(7,"xiaoqiang");
		map.put(6,"wangcai");
		/*
		取出map中的所有元素。
		原理:通过keySet()方法获取Map中所有的键所在的Set集合,再通过Set的迭代器获取到每一个键,
		再对每一个键通过get(key)方法获取其对应的值即可。
		*/
		Set<Integer> keySet = map.keySet();
		Iterator<Integer> it = keySet.iterator();
		while(it.hasNext()) {
			Integer key = it.next();
			String value = map.get(key);
			System.out.println(key + "..." + value);
		}
	}
}

3,图解:


17-4,重点方法entrySet演示图解

1,public Set<Map.Entry<k,v>>entrySet(),返回此映射锁包含的映射关系的set视图。

2,第二种取出方式entrySet(),

public class Demo {
	public static void main(String[] args) {
		Map<Integer,String> map = new HashMap<Integer,String>();
		method(map);
	}
	public static void method(Map<Integer,String> map) {
		map.put(8,"zhaoliu");
		map.put(2,"wangwu");
		map.put(7,"xiaoqiang");
		map.put(6,"wangcai");
		/*
		取出map中的所有元素。
		原理:通过Map转换成set就可以迭代,这里使用另一种方法:entrySet()。
		该方法将键和值的映射关系作为对象存储到了set集合中,而这个映射关系的类型就是Map.Entry类型。
		*/
		Set<Map.Entry<Integer,String>> entrySet = map.entrySet();
		Iterator<Map.Entry<Integer,String>> it = entrySet.iterator();
		while(it.hasNext()) {
			Map.Entry<Integer,String> me = it.next();
			Integer key = me.getKey();
			String value = me.getValue();
			System.out.println(key + "..." + value);
		}
	}
}

3,图解:


4,Map.Entry的解释

Map是个接口,Map.Entry是接口中的接口,即,内部接口,表现如下:

interface Map {
	public static interface Entry {
		void get();
	}
}
class Demo implements Map.Entry {
	public void get() {...}
}

这与内部类差不多是一个原理。

 

17-5,方法values()的演示

1,Collection<V> values()

返回此映射中包含的值得Collection视图。

返回Collection而不是Set的原因是:键是唯一的,而值不是唯一的,所以不能用Set存。

2,演示

public class Demo {
	public static void main(String[] args) {
		Map<Integer,String> map = new HashMap<Integer,String>();
		method(map);
	}
	public static void method(Map<Integer,String> map) {
		map.put(8,"zhaoliu");
		map.put(2,"wangwu");
		map.put(7,"xiaoqiang");
		map.put(6,"wangcai");
		Collection<String> values = map.values();
		Iterator<String> it = values.iterator();
		while(it.hasNext()) {
			System.out.println(it.next());
		}
	}
}

 

17-6,Map常用子类对象

1,Map常用子类:

(1)Hashtable:内部结构是哈希表,是同步的,不允许null作为键、值。

(2)HashMap:内部结构是哈希表,不是同步的,允许null作为键、值。

(3)TreeMap:内部结构是二叉树,不是同步的。可以对Map集合中的键进行排序。

HashSet其实是一个HashMap的实例,他的底层代码是根据HashMap实现的。

2,Hashtable

Hashtable下有一个子类是Properties,表示了一个持久的属性集,用来存储键值对型的配置文件的信息,可以和IO技术相结合使用。

 

17-7,HashMap存储自定义对象

1,将Person对象和Person的归属地通过键与值存储到Map集合中。

//先定义Person类
public class Person {
	private String name;
	private int age;
	Person(String name,int age) {
		this.name = name;
		this.age = age;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getAge() {
		return this.age;
	}
}
public class Demo {
	public static void main(String[] args) {
		HashMap<Person,String> hm = new HashMap<Student,String>();
		hm.put(new Person("lisi",38),"北京");
		hm.put(new Person("zhaoliu",24),"上海");
		hm.put(new Person("xiaoqiang",31),"沈阳");
		hm.put(new Person("wangcai",28),"大连");
		hm.put(new Person("zhaoliu",24),"铁岭");
		Iterator<Person> it = hm.keySet().iterator();
		while(it.hasNext()) {
			Person key = it.next();
			String value = hm.get(key);
			System.out.println(key.getName()+":"+key.getAge()+value);
		}	
	}
}

直接这样打印,五个人都会被打印出来,但我们认为键相同则会覆盖,这就必须在Person类中覆写hashCode()和equals()方法,是Student对象具备比较功能,这样就可以不重复取出了。

 

17-8,TreeMap存储自定义对象

与TreeSet一样,TreeMap也具备自定义排序的功能,他是根据Key排序的,Key的对象要实现Comparable接口,并覆写其compareTo方法,下面示例根据Person的age排序的实现。

public class Person {
	private String name;
	private int age;
	Person(String name,int age) {
		this.name = name;
		this.age = age;
	}
	public void setName(String name) {
		this.name = name;
	}
	public String getName() {
		return this.name;
	}
	public void setAge(int age) {
		this.age = age;
	}
	public int getAge() {
		return this.age;
	}
	public int compareTo(Object o) {
		Person p = (Person)o;
		int temp = this.age - p.age;
		return temp == 0 ? this.name.compareTo(p.name) : temp;
	}
}
public class Demo {
	public static void main(String[] args) {
		TreeMap<Person,String> tm = new TreeMap<Person,String>();
		tm.put(new Person("lisi",38),"北京");
		tm.put(new Person("zhaoliu",24),"上海");
		tm.put(new Person("xiaoqiang",31),"沈阳");
		tm.put(new Person("wangcai",28),"大连");
		tm.put(new Person("zhaoliu",24),"铁岭");
		Iterator<Map.Entry<Person,String>> it = tm.entrySet().iterator();
		while(it.hasNext()) {
			Map.Entry<Person,String> me = it.next();
			Person key = me.getKey();
			String value = me.getValue();
			System.out.println(key.getName()+":"+key.getAge()+value);
		}	
	}
}

Person实现了Comparable接口,其compareTo方法是按照年龄排序的,所以上述程序打印结果是按照年龄排序的。

这个TreeMap也可以通过比较器来排序,只要在创建TreeMap对象时,直接将比较器的实例对象作为实参传给其构造函数即可。

public class ComparatorsByName implements Comparator {
	public int compare(Object o1,Object o2) {
		Person p1 = (Person)o1;
		Person p2 = (Person)o2;
		int temp = p1.getName().compareTo(p2.getName());
		return temp == 0 ? p1.getAge() - p2.getAge() : temp;
	}
}

...

构建的时候:

TreeMap<Person,String> tm = newTreeMap<Person,String>(new ComparatorByName());

 

17-9,LinkedHashMap

需求:让HashMap中的元素有序的取出来,即怎么存的就怎么取出。

直接在HashMap的前面加上Linked就可以了。

如:HashMap<Integer,String> hm =new LinkedHashMap<Integer,String>();

加上链表结构就可以有序存入取出了。

 

17-10,Map集合-练习

需求:记录字母出现的次数。

"fdgavcbsacdfs",获取该字符串中每一个字母出现的次数,

要求打印结果格式:a(2)b(1)...

思路:

对于结果的分析发现,字母和数字之间存在着映射关系。而且这种关系很多,很多数据就需要存储起来,能存储映射关系的容器有数组和Map集合。

那么还要思考,数组是基于角标的,角标是有序的编码,在本题中,映射关系的一方是有序的编码么?不是的,所以应该使用Map集合,又发现可以保证唯一性的一方具备这顺序,如a,b,c...,所以可以使用TreeMap集合。

这个集合最终应该存储的是字母和次数的对应关系。

(1)因为操作的是字符串中的字母,所以先将字符串编程字符数组。

(2)遍历字符数组,用每一个字母作为键去查Map集合这个表。如果该字母键不存在,就将该字母作为键,1作为值存入到Map集合中。如果该字母键不存在,就将该字母键对应值取出并+1,再将该字母+1后的值存储到Map集合中。

(3)遍历结束,map集合就记录所有的字母出现的次数。

public class MapTest {
	public static void main(String[] args) {
		String str = "fdg+avAdc  bs50da9c-fds";
		String s = getCharCount(str);
		System.out.println(s);
	}
	public static String getCharCount(String str) {
		char[] chs = str.toCharArray();
		Map<Character,Integer> map = new TreeMap<Character,Integer>();
		for(int i = 0 ; i < chs.length ; i++) {
			if(!(chs[i]>='a'&&chs[i]<='z'||chs[i]>='A'&&chs[i]<='Z'))
				continue;
			Integer value = map.get(chs[i]);
			int count = 1;
			if(value != null)
				count = value + 1;
			map.put(chs[i],count);
		}
		return mapToString(map);
	}
	private static String mapToString(Map<Character,Integer> map) {
		StringBuilder sb = new StringBuilder();
		Iterator<Charactor> it = map.keySet().iterator();
		while(it.hasNext()) {
			Charactor key = it.next();
			Integer value = map.get(key);
			sb.append(key+"("+value+")");
		}
		return sb.toString();
	}
}

17-11,Map查表法练习

1,Map在有映射关系时可以优先考虑,在查表法中的应用较为多见。

2,若要查一班的张三,一班的李四怎么办?

    map.put("一班","张三");

map.put("一班","李四");

这是不行的,键相同,李四会把张三覆盖。

可以在值得位置上加一个集合,如:map.put("一班",Set<String>);这样一班就对应一个集合了。

3,查表法练习-星期

public class MapTest {
	public static void main(String[] args) {
		String week = getWeek(1);
		System.out.println(week);
		System.out.println(getWeekByMap(week));
	}
	public static String getWeekByMap(String week) {
		Map<String,String> map = new HashMap<String,String>();
		map.put("星期一","Mon");
		map.put("星期二","Tus");
		map.put("星期三","Wed");
		map.put("星期四","Thu");
		map.put("星期五","Fri");
		map.put("星期六","Sat");
		map.put("星期日","Sun");
		map.put("星期天","Sun");
		return map.get(week);
	}
	public static String getWeek(int week) {
		if(week < 1 || week > 7) {
			throw new RuntimeException("没有对应的星期");
		}
		String[] weeks = {"","星期一","星期二","星期三","星期四","星期五","星期六","星期日"};
		return weeks[week];
	}
}


猜你喜欢

转载自blog.csdn.net/xzm_rainbow/article/details/17892319
今日推荐