------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
Map集合概述
Map集合中可以存储两个元素,而且是一对一对的存储,并且要保证键的唯一性,表示方式是Map<K,V> ,这里的K表示键,V表示值,两者之间存在着一种映射关系,因此我们又成Map集合是双列集合。
Map集合的共性方法
void clear() 清空集合中所有的键值
boolean containsKey(Object key) 判断集合中是否包含指定的键。
<Set<Map.Entry<K,V>> entrySet() 返回映射中包含映射关系的Set视图。
V get(Object key) 给定一个键,返回值。
V put(K key, V value)将指定的键值对存储到集合中。
V remove(Object key)根据指定的键,移除映射关系。
Map集合对应的三个常见的重要的子类:
Hashtable:底层是哈希表数据结构,不可以存入null作为键,也不可以存入null作为值。出现在jdk1.0,该集合是线程同步的。
HashMap:底层是哈希表数据结构,并允许使用空键空值,该集合是不同步。出现在jdk1.2,效率高。
TreeMap:底层是二叉树数据结构,线程不同步,可以用于给Map集合中的键进行排序。
Map和Set集合很像。其实Set底层就是使用了Map集合。
Map实例一:
/*
Map集合:
增
put(key,value)
putAll(map)
删
remove(key)
改
查
containsKey()判断集合中是否包含某个键。
get(key)根据键获取所对应的值。
values();获取map集合中所有值的Collection值。
seize()
*/
import java.util.*;
class JavaCollection1_23
{
public static void main(String[] args)
{
Map<String,String> map=new HashMap<String,String>();
//添加元素。如果添加元素,添加了相同的键,那么后添加的值为覆盖原有键所对应的值。并钱put方法会返回被覆盖的那个值。
//注意这里put
sop(map.put("01","xt"));
sop(map.put("01","x"));
map.put("02","hj");
map.put("03","wmz");
sop(map);
sop(map.containsKey("01"));
//删除元素 注意这里的remove删除成功后并还会返回键所对应的值,如果要删除的key不在map集合中,那么将返回null
sop(map.remove("02"));
sop(map.remove("0022"));
sop(map);
//如果该键在集合不存在,那么也回返回null,根据这种方法我们可以判断集合中是否包含某个键。注意HashMap中可以存储null值,但是hashtable中不可以存储null键null值。
map.put(null,"fff");
sop(map.get("01"));
sop(map.get("003"));
sop(map);
//values
Collection c=map.values();
sop(c);
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
获取map集合中全部键值的两种方式。
第一种方式是先获取map集合中的键,并将其存储到一个Set集合中,因为Set集合自身具备迭代行,那么我们可以迭代每一个键,然后调用map集合的get()方法,就可以获取当前的键所对应的值。
map示例二:
import java.util.*;
class JavaCollection1_24
{
public static void main(String[] args)
{
Map<String,String> map=new HashMap<String,String>();
map.put("01","xt");
map.put("02","hj");
map.put("03","wmz");
//获取map集合中所有的键对应的Set集合
Set<String> keyset=map.keySet();
for(Iterator<String> it=keyset.iterator();it.hasNext();)
{
String key=it.next();
String value=map.get(key);
System.out.println(key+"="+value);
}
}
}
运行结果如下:
第二种方式就是集合中的映射关系存储到Set<Map.Entry>集合中,而这个映射关系包含对应的键和对应的值,这种映射关系就是用Map.Entry>来表示。
Map集合示例三:
import java.util.*;
class JavaCollection1_25
{
public static void main(String[] args)
{
Map<String,String> map=new HashMap<String,String>();
map.put("01","xt");
map.put("02","hj");
map.put("03","wmz");
//获取map集合中全部对应的映射关系。
Set<Map.Entry<String,String>> entryset=map.entrySet();
for(Iterator<Map.Entry<String,String>>it=entryset.iterator();it.hasNext();)
{
//根据Map.Entry 对象所对应的方法getKey(),getValue()方法获取当前映射关系的键和值。
Map.Entry<String,String> me=it.next();
String key=me.getKey();
String value=me.getValue();
System.out.println(key+"="+value);
}
}
}
运行的结果同上。
其实我们通过查文档,可以发现Map.Entry其实也是Map接口中的一个内部接口。而HashMap类实现了Map接口,那又是谁来实现Entry接口的呢?通过查资料我们可以发现是HashMap中的匿名内部来实现的,因此,总结可得如下的关系:
interface Map
{
static interface Entry
{
public abstract Object getValue();
public abstarct Object getKey();
}
}
class HashMap implements Map
{
class NoNameClass implements Entry
{
public Object getValue()
{
……
}
public Object getKey()
{
……
}
}
}
Map集合示例四:
需求:
每一个学生都有自己的归属地,学生的属性:姓名,年龄,注意:姓名和年龄相同的学生视为同一个人,保证学生的唯一性。
/*
1 描述学生
2 将学生作为键,地址作为值存入到Map集合中
3获取Map集合中的元素
*/
import java.util.*;
class JavaCollection1_28
{
public static void main(String[] args)
{
HashMap<Student,String> hm=new HashMap<Student,String>();
hm.put(new Student("xt",45),"beijing");
hm.put(new Student("t",23),"shanghai");
hm.put(new Student("at",44),"tianjing");
hm.put(new Student("dft",45),"wuhan");
//这里插入了一条重复的记录,所以在map集合中会覆盖以前的值,上面的地址也就会变成yunnan.
hm.put(new Student("dft",45),"yunnan");
//第一种方式keySet先获取键,然后进行遍历
Set<Student> keyset=hm.keySet();
for(Iterator<Student> it=keyset.iterator();it.hasNext();)
{
Student s=it.next();
System.out.println(s.getName()+":"+s.getAge()+"-----"+hm.get(s));
}
System.out.println("*******************************");
//第二种方式先获取<Map.Entry>映射关系,然后在进行遍历
Set<Map.Entry<Student,String>> entryset=hm.entrySet();
for(Iterator<Map.Entry<Student,String>> it=entryset.iterator();it.hasNext();)
{
Map.Entry<Student,String> me=it.next();
Student s=me.getKey();
String address=me.getValue();
System.out.println(s.getName()+":"+s.getAge()+"------"+address);
}
}
}
//注意这样的学生有可能存储到Set这样的集合中,因此我们必须按照自己的要求,保证学生的唯一性,所以必须覆盖hashCode和equals方法,另外,这个学生对象有可能存储到二叉树这样的数据结构中去,比如TreeSet这样的集合中去,所以我们也应该实现Comparator或者Comparable接口,让学生自身具备比较顺序。
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int hashCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型转换失败");
else
{
Student s=(Student)obj;
return this.name.equals(s.getName())&&this.age==s.getAge();
}
}
public int compareTo(Student s)
{
int num=this.age-s.age;
if(num==0)
{
return this.name.compareTo(s.getName());
}
return num;
}
}
运行结果:
Map集合额示例五:
需求:对学生对象要进行排序(先按照姓名排序,然后在按照年龄排序),因为数据时以键值对的形式存在的,那么我们需要使用TreeMap这个集合;
代码如下:
import java.util.*;
class JavaCollection1_29
{
public static void main(String[] args)
{
//将自定义的比较器对象作为参数传递给TreeMap,这样就使集合具备了比较性。
TreeMap<Student,String> tm=new TreeMap<Student,String>(new MyComp());
tm.put(new Student("xt",45),"beijing");
tm.put(new Student("t",23),"shanghai");
tm.put(new Student("at",44),"tianjing");
tm.put(new Student("dft",45),"wuhan");
//这里插入了一条重复的记录,所以在map集合中会覆盖以前的值,上面的地址也就会变成yunnan.
//tm.put(new Student("dft",45),"yunnan");
//第一种方式keySet先获取键,然后进行遍历
Set<Student> keyset=tm.keySet();
for(Iterator<Student> it=keyset.iterator();it.hasNext();)
{
Student s=it.next();
System.out.println(s.getName()+":"+s.getAge()+"-----"+tm.get(s));
}
System.out.println("*******************************");
//第二种方式先获取<Map.Entry>映射关系,然后在进行遍历
Set<Map.Entry<Student,String>> entryset=tm.entrySet();
for(Iterator<Map.Entry<Student,String>> it=entryset.iterator();it.hasNext();)
{
Map.Entry<Student,String> me=it.next();
Student s=me.getKey();
String address=me.getValue();
System.out.println(s.getName()+":"+s.getAge()+"------"+address);
}
}
}
//定义了一个比较器,先安装学生的姓名进行排序,如果学生的姓名相同,在比较学生的年龄
class MyComp implements Comparator<Student>
{
public int compare(Student s1,Student s2)
{
int num=s1.getName().compareTo(s2.getName());
if(num==0)
{
return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));
}
return num;
}
}
class Student implements Comparable<Student>
{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
public int hashCode()
{
return name.hashCode()+age*34;
}
public boolean equals(Object obj)
{
if(!(obj instanceof Student))
throw new ClassCastException("类型转换失败");
else
{
Student s=(Student)obj;
return this.name.equals(s.getName())&&this.age==s.getAge();
}
}
public int compareTo(Student s)
{
int num=this.age-s.age;
if(num==0)
{
return this.name.compareTo(s.getName());
}
return num;
}
}
运行结果如下:
从上面的结果我们可以看出,先是按照姓名排序,然后在按照年龄进行排序的。
Map实例六:
需求:统计一个字符串中字符的个数,如字符串("abcdacd") 按照如下结果输出a(2)b(1)c(2)d(2)
思路:1先将字符串转换成字符数组
2因为输出的是按字母的顺序输出的,所以我们要使用TreeMap这个集合。
3然后遍历每个字符,然后将每个字符作为键去查map集合,如果返回null,那么就将改字符和次数1存入到集合中,如果返回不为null,说明该字符在集合中已经存在,并且有对应的次数,那么就将该字符和自增后的次数添加到map集合中,
4遍历集合,输出对应的格式。
代码如下:
import java.util.*;
class JavaCollection1_30
{
public static void main(String[] args)
{
String RetVal=getCharacterSor("abfcdaefbds");
sop(RetVal);
}
public static String getCharacterSor(String str)
{
char [] arr=str.toCharArray();
TreeMap<Character,Integer> tm=new TreeMap<Character,Integer>();
for(int i=0;i<arr.length;i++)
{
Integer value=tm.get(arr[i]);
if(value==null)
{
value=1;
tm.put(arr[i],value);
}
else
{
value+=1;
tm.put(arr[i],value);
}
}
StringBuilder sb=new StringBuilder();
Set<Map.Entry<Character,Integer>>entryset=tm.entrySet();
for(Iterator<Map.Entry<Character,Integer>> it=entryset.iterator();it.hasNext();)
{
Map.Entry<Character,Integer> me=it.next();
sb.append(me.getKey()+"("+me.getValue()+")");
}
return sb.toString();
}
public static void sop(Object obj)
{
System.out.println(obj);
}
}
运行结果如下:
通过上述例子我们发现, 只要如果具备映射关系时,就可以使用Map集合。
Map集合扩展
在开发过程中,映射关系往往不只是简单的一对一关系,有很多情况下是一对多的映射关系,而在这种情况下,我们往往要使用嵌套映射来解决问题
Map实例七:
需求:创建一个学校,而一个学校里有多个班,每个班中有多个学生,自定义数据,显示每个班上对应的学生。
分析:学校(1)----->班级(n)----------->学生(m)
代码如下:
import java.util.*;
class JavaCollection1_31
{
public static void main(String[] args)
{
//1创建一个学校
HashMap<String,HashMap<String,Integer>> school=new HashMap<String,HashMap<String,Integer>>();
//2创建多个班级
HashMap<String,Integer> class1=new HashMap<String,Integer>();
HashMap<String,Integer> class2=new HashMap<String,Integer>();
//3创建多个学生
class1.put("zhangsan",12);
class1.put("lisi",16);
class2.put("wangwu",18);
class2.put("zhaoliu",19);
//将创建的班级添加到学校中
school.put("class1",class1);
school.put("class2",class2);
Set<Map.Entry<String,HashMap<String,Integer>>> entryset=school.entrySet();
for(Iterator<Map.Entry<String,HashMap<String,Integer>>> it =entryset.iterator();it.hasNext();)
{
Map.Entry<String,HashMap<String,Integer>> me=it.next();
String temp_class=me.getKey();
System.out.println(temp_class);
showDetailClassMsg(me.getValue());
}
}
public static void showDetailClassMsg(HashMap<String,Integer> hm)
{
Set<String> keyset=hm.keySet();
for(Iterator<String> it=keyset.iterator();it.hasNext();)
{
String name=it.next();
Integer age=hm.get(name);
System.out.println(name+":"+age);
}
}
}
运行结果如下:
其实通过上面的代码,只是为了说明这种关系,但是在真的开发中,上面的这种写法,并不常见,因为通过观察我们发现,其实发现学生对象还可以进行封装,于是我们改进代码。让其变得更通俗易懂点。
import java.util.*;
class JavaCollection1_32
{
public static void main(String[] args)
{
//1创建一个学校,用于存储班级
HashMap<String,List<Student>> school=new HashMap<String,List<Student>>();
//2创建多个班级
ArrayList<Student> class1=new ArrayList<Student>();
ArrayList<Student> class2=new ArrayList<Student>();
//3创建多个学生
class1.add(new Student("zhangsan",20));
class1.add(new Student("lisi",21));
class2.add(new Student("wanglu",32));
class2.add(new Student("zhaoliu",33));
//4将班级添加到学校中
school.put("class1",class1);
school.put("class2",class2);
//遍历输出所有班级中对应的学生
Set<Map.Entry<String,List<Student>>> entryset=school.entrySet();
for(Iterator<Map.Entry<String,List<Student>>> it=entryset.iterator();it.hasNext();)
{
Map.Entry<String,List<Student>> me=it.next();
String temp_class=me.getKey();
System.out.println(temp_class);
showClassDetailMsg(me.getValue());
}
}
public static void showClassDetailMsg(List<Student> list)
{
for(int i=0;i<list.size();i++)
{
Student s=list.get(i);
System.out.println(s.getName()+":"+s.getAge());
}
}
}
class Student
{
private String name;
private int age;
Student(String name,int age)
{
this.name=name;
this.age=age;
}
public String getName()
{
return name;
}
public int getAge()
{
return age;
}
}
运行结果如下: