JAVA常用集合框架用法详解基础篇四之Map接口

这一篇我们说说集合框架的另一个家族Map接口。它是和Colletion接口是并列为集合框架的始祖啊。

一、Map接口

Map<K,V>,一次添加一对元素(又称键值对)。K是键,V是值。而Collection一次添加一个元素。Map集合也称为双列集合,Collection集合也称为单列集合。其实Map集合中存储的就是键值对,且保证键(K)的唯一性。

Map常用的子类:

1、Hashtable:内部结构是哈希表,是同步的。不支持null作为键和值。

2、HashMap:内部结构是哈希表,不是同步的,支持null作为键和值。

3、TreeMap:内部结构是二叉树,不是同步的,支持null作为键和值。

Map接口常用的方法如下:

1、添加

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

2、删除

value  remove(key);//根据指定的key删除这个键值对
void clear();//清除这个Map集合

3、判断

boolean  containsKey(key);
boolean  containsValue(value);
boolean  isEmpty();//判断是否为空

4、获取

value get(key);//用过键来返回值,如果没值该键返回null。当然可以通过返回null来判断是否包含指定的键(K) 
int size();//获取键值对的个数

二、Map接口是如何实例化的,如何遍历元素的??

这里演示一个HashMap实例化的例子:

Map<Integer,String> map=new HashMap<Integer,String>();//实例化一个HashMap对象

注意:问题:如何获取map中的所有的元素???

取出map中的元素,原理如下:通过keySet方法获取map中所有键所在的Set集合中,再通过Set的迭代器获取到每个键。然后对每个键通过map集合的get()方法获取其所对应的值。


代码演示如下:

package com.wq.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;

/**
 * 测试Map的一些基本的方法
 * 
 * @author LULEI
 *
 */
public class mapDemo1 {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Map<Integer, String> hm=new HashMap<Integer,String>();//实例化对象
		
		testMapDemo1(hm);//这个方法实现了一些基本方法
		
		System.out.println();
		System.out.println();
		testMapDemo2(hm);	//这个方法实现Map集合中如何取出所有的元素
					//1、要使用到keySet()方法来获取key值得Set集合
					//2、依次的迭代Set集合中的key值,最后通过get(key)来获取键值对
		
	}

	public static void testMapDemo2(Map<Integer, String> hm) {
		// TODO Auto-generated method stub
		String str2=hm.put(2, "lisi");
		//System.out.println("此时给相同的key赋键值,返回的上一个键值是:"+str2);//此时lisi								//会覆盖wangcai的,同时put方法会返回之前的键值对
		hm.put(8, "wq");
		hm.put(7, "ll");
		hm.put(6, "pp");
		
		Set<Integer> s=hm.keySet();//获取key的Set集合
		//使用迭代器来迭代集合
		for(Iterator<Integer> it=s.iterator(); it.hasNext();){
			Integer i=it.next();
			System.out.println("使用迭代获取的元素:"+hm.get(i)  );
		}
		
	}

	public static void testMapDemo1(Map<Integer, String> hm) {
		//添加
		String str1=hm.put(2, "wangcai");
		System.out.println("此时给相同的key赋键值,返回的上一个键值是:"+str1);//此时由于key刚刚被赋值,所以之前是没有键值对的
		String str2=hm.put(2, "lisi");
		System.out.println("此时给相同的key赋键值,返回的上一个键值是:"+str2);//此时lisi会覆盖wangcai的,同时put方法会返回之前的键值对
		hm.put(7, "ll");
		hm.put(8, "wq");
		hm.put(6, "pp");
		System.out.println("所有的键值对如下:"+hm);
		//获取
		System.out.println("获取相应的key值得键值:"+hm.get(7));
		System.out.println("获取相应的key值得键值:"+hm.get(4));
		//删除
		hm.remove(6);//删除key为6的键值
		System.out.println("删除key为6的键值后的map"+hm);
	}

}

运行结果如下:

此时给相同的key赋键值,返回的上一个键值是:null

此时给相同的key赋键值,返回的上一个键值是:wangcai

所有的键值对如下:{2=lisi,6=pp, 7=ll, 8=wq}

获取相应的key值得键值:ll

获取相应的key值得键值:null

删除key为6的键值后的map{2=lisi, 7=ll, 8=wq}

 

使用迭代获取的元素:lisi

使用迭代获取的元素:pp

使用迭代获取的元素:ll

使用迭代获取的元素:wq

 上面提到的只是一种方法,另一种方法是entrySet()。该方法将键与值得映射关系作为对象存储到了Set集合中,而这个映射关系的类型就是Map.EntryKey类型。(打个比方:键是丈夫,值就是妻子,映射关系就是结婚证)。Entry本身就是一个嵌套的静态接口。 

图解如下:


代码演示如下:

//Person类
package com.wq.person;

public class Person extends Object implements Comparable{
		private String name;
		private int age;
		
		public Person() {
			super();
			// TODO Auto-generated constructor stub
		}
		public Person(String name, int age) {
			super();
			this.name = name;
			this.age = 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 int hashCode() {
			final int prime = 31;
			int result = 1;
			result = prime * result + age;
			result = prime * result + ((name == null) ? 0 : name.hashCode());
			return result;
		}
		@Override
		public boolean equals(Object obj) {
			if (this == obj)
				return true;
			if (obj == null)
				return false;
			if (!(obj instanceof Person))
				return false;
			Person other = (Person) obj;
			if (age != other.age)
				return false;
			if (name == null) {
				if (other.name != null)
					return false;
			} else if (!name.equals(other.name))
				return false;
			return true;
		}
		@Override
		public String toString() {
			// TODO Auto-generated method stub
			return name+"...."+age;
		}
		//需要覆写的compareTo方法
		//这里我的思路是先比较age的大小,如果age相等,则
		//接着比较name的字典顺序大小
		@Override
		public int compareTo(Object o) {
			// TODO Auto-generated method stub
			Person per=(Person) o;//实现强制类型转换
			if(this.age>per.age){
				return 1;
			}else if(this.age<per.age){
				return -1;
			}else{//如果年纪相等就比较名字的字典顺序大小
				int temp=this.name.compareTo(per.name);
				return temp;
			}
			
			
		}
		
}

	//student类继承Person类
package com.wq.person;

public class Student extends Person{
	private String name;
	private int age;
	public Student(String name, int age) {
	
		super(name,age);
	}
	public Student(){
		super();
	}
	@Override
	public String toString() {
		return "Student [name=" + name + ", age=" + age + "]";
	}
		
}



	//测试HashMap类
package com.wq.map;

import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;

import com.wq.person.Student;

public class Hashmaptest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		HashMap<Student,String> hm=new HashMap<Student,String>();
		//添加学生对象,和学生的归属地
		hm.put(new Student("lisi",24 ),"南京");
		hm.put(new Student("zhangsan",44 ),"北京");
		hm.put(new Student("wangwu",32 ),"天津");
		hm.put(new Student("xiaoqiang",18 ),"上海");
		hm.put(new Student("xiaoqiang",18 ),"后海");
		
		Set<Student> s=hm.keySet();
		Iterator<Student> it=s.iterator();
		while(it.hasNext()){
			Student st=it.next();
			String value=hm.get(st);
			System.out.println(st.getName()+".."+st.getAge()+"...."+value);
		}
	}

}

运行代码如下:

xiaoqiang..18....后海

wangwu..32....天津

zhangsan..44....北京

lisi..24....南京


//测试TreeMap类
//自定义比较器
package com.wq.comparator;

import java.util.Comparator;

import com.wq.person.Person;

public class ComparatorByName implements Comparator {

	/**
	 * 覆写compare方法,生成一个比较器。这里我们用name的字典顺序来作为比较
	 */
	@Override
	public int compare(Object o1, Object o2) {
		// TODO Auto-generated method stub
		Person p1=(Person)o1;
		Person p2=(Person)o2;
		
		int temp=p1.getName().compareTo(p2.getName());//获取两个对象的name比较的结果
		return temp==0?p1.getAge()-p2.getAge():temp;
	}

}



//TreeMap测试部分
package com.wq.map;

import java.util.Comparator;
import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

import com.wq.comparator.ComparatorByName;
import com.wq.person.Student;

public class TreeMaptest {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//添加一个比较器,用来排序
		TreeMap<Student,String> hm=new TreeMap<Student,String>(new ComparatorByName());
		//添加学生对象,和学生的归属地
		hm.put(new Student("lisi",24 ),"南京");
		hm.put(new Student("zhangsan",44 ),"北京");
		hm.put(new Student("wangwu",32 ),"天津");
		hm.put(new Student("xiaoqiang",18 ),"上海");
		hm.put(new Student("xiaoqiang",28 ),"后海");
		
		//使用entrySet来获取全部元素
		Iterator<Map.Entry<Student, String>> it=hm.entrySet().iterator();
		
		while(it.hasNext()){
			Map.Entry<Student, String> mp=it.next();
			Student st=mp.getKey();
			String value=mp.getValue();
			System.out.println(st.getName()+".."+st.getAge()+"...."+value);
		}
	}

}

运行结果:

lisi..24....南京

wangwu..32....天津

xiaoqiang..18....上海

xiaoqiang..28....后海

zhangsan..44....北京

  

相信以上的代码能够帮助我们更好地理解Map的子类。以及获取所有子类元素的方法:keySet()和EntrySet()两种方法。接下来看看练习:

 

习题:” aFGDHRTYdshgfd./,/g1uAAD898 styefbhbhad”,这样一个随机的字符串。获取该字符串中每个字符出现的次数。并最终以a(n),b(m)……这样的格式打印出来。

 

分析如下:对于结构的显示,字符和出现次数之间存在着映射的关系。而且这种关系很多。既然很多我们就需要存储,但是能存储映射关系的有数组和Map集合。这时我们需要考虑:关系一方有序号编码吗?答案是没有,于是我们就选用Map集合,同时又发现可以保证唯一性的一方具备着顺序如:a,b,c,d,……。所以最后的选择是TreeMap集合。

 

操作思路:这个集合最后存储的是字符与次数的对应关系。

1、因为操作的是字符串中的字符,所以先将字符串变成字符数组。

2、遍历字符数组,用每一个字符作为键去查询Map集合这个表。

3、如果该键不存在,就将该字母作为键,1作为值,存储到Map集合中。

4、如果该键存在,就将该字符键对应的值加1,在将该字母与加1后的值存在Map集合中。键相同,只会覆盖,这样就记录了字符的次数。

5、遍历字符数组结束后,Map集合就记录了所有的字符出现的次数。一次迭代输出即可是实现。

 

代码实现如下:

package com.wq.map;

import java.util.Iterator;
import java.util.Map;
import java.util.TreeMap;

/**
 * 练习:" aFGDHRTYdshgfd./,/g1uAAD898 styefbhbhad "获取该字符串中,
 * 每一个字母出现的次数,要求打印的结果如下
 * a(1)b(2)c(..)...
 * @author LULEI
 *
 */
public class MapPrictice {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		//声明要变换的字符串
		String str="aFGDHRTYdshgfd./,/g1uAAD898 styefbhbhad";
		str=StringTocharNum(str);
		System.out.println(str);
	}

	public static String StringTocharNum(String str) {
		// TODO Auto-generated method stub
		//1、第一步是将字符串转换成字符数组
		char[] ch=str.toCharArray();
		
		//2、定义一个map集合,用于存储字母(键)和出现的次数(值)
		Map<Character,Integer> mp=new TreeMap<Character,Integer>();
		//3、开始进行循环的判断
		
		//当出现非字母的字符时,增加如下的判断
		
		for (int i = 0; i < ch.length; i++) {
			if(!(ch[i]>='a' && ch[i]<='z'|| ch[i]>='A' && ch[i]<='Z')){
				continue;//如果不是字符则结束本次循环
			}
			Integer value=mp.get(ch[i]);//注意这里返回的是int的包装类。之前Map是这样定义的Map<Character,Integer>
			if(value==null){
				mp.put(ch[i], 1);
			}else{
				mp.put(ch[i], value+1);
			}
		}
		//4、将字母以次数打印出来
		return printCharNum(mp);//调用打印函数
	}

	private static String printCharNum(Map<Character, Integer> mp) {
		
		//定义一个可以改变字符长度的字符串
		StringBuilder sb=new StringBuilder();
		//取出Map中的所有元素
		Iterator<Character> it=mp.keySet().iterator();
		while(it.hasNext()){
			Character ch=it.next();
			Integer in=mp.get(ch);
			sb.append(ch+"("+in+")");//直接在后面添加字符串
		}
		return sb.toString();//最后转换为string类型输出
	}

}

运行结果如下:

A(2)D(2)F(1)G(1)H(1)R(1)T(1)Y(1)a(2)b(2)d(3)e(1)f(2)g(2)h(3)s(2)t(1)u(1)y(1)


XXiaoLEI整理于2015-04-06 。


  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值