Map概述
现实生活中,我们常会看到这样一种组合,IP地址和主机名,身份证号和个人,系统用户名与系统用户对象,这种一一对应的关系,就叫做映射。java提供了专门的集合类用来存储这种对象关系的集合,即java.util.Map接口。
我们可以查看Map接口的描述,发现Map接口下的集合与Collection接口下的集合他们的存储形式不同;
如图:
collection中的集合,元素是孤立的(理解为单身),集合中存储元素采用一个一个元素的方式存储
Map中的集合,元素是成对存在的(理解为夫妻),每个元素由键与值两部分组成,通过键可以找到对应的值。
collection中的集合为单列集合,Map中的集合为双列集合
需要注意的是,map中的集合不能包含重复的键,值可以重复,每个键只能对应一个值。
Map常用子类
通过查看Map接口的描述,看到Map集合中有N多个子实现类,这里我们主要讲解常用的HashMap集合、LinkednHashMap集合。
hashMap 存储数据采用的哈希表结构,元素的存取顺序不能保证一致,由于要保证键的唯一,不重复。需要重写键的hashCode方法和equals方法。
LinkedHashMap 在hashMap下面有个子类,LinkedHashMap,存储数据采用的哈希表结构+链表结构,通过链表结构可以保证元素的存取顺序一致,通过哈希表结构可以保证键的唯一,不重复,需要重写键的hashCode方法和equals方法。
注意: Map接口中泛型变量,K,V,在使用的时候,要为两个泛型变量赋予数据类型,两个泛型变量的数据类型可以相同,也可以不同
Map接口中常用方法
- public V put(K key,V value) 把指定的键与值添加到Map集合中
- public V remove(Object key) 把指定的键所对应的值元素,在Map集合中移除,并返回该删除的元素的值
- public V get(Object key) 根据指定的键,获取对应的值
- public containsKey(Object key) 判断集合中是否包含指定的键
- public Set keySet() 获取map集合中所有的键,存储到set集合中
- public Set> entrySet() 获取到Map集合中所有的键值对对象的set集合
代码演示:
public static void main(String[] args) {
//创建Map对象
HashMap<String, String> map = new HashMap<>();
//添加元素到集合
map.put("黄晓明","杨颖");
map.put("文章","马伊利");
map.put("谢霆锋","张柏芝");
map.put("王宝强","马蓉");
map.put("邓超","孙俪");
//打印一下集合内容
System.out.println(map);
//移除键为邓超的元素
System.out.println(map.remove("邓超"));
System.out.println(map);
//查看key 对应的值
System.out.println(map.get("黄晓明"));
System.out.println(map.get("邓超"));
//修改
map.put("黄晓明","卑鄙");
System.out.println(map);
}
注意:
使用put方法时,若指定的键在集合中没有,则没有这个键对应的值,返回null。并把指定的键、值添加到集合中。
若指定的键在集合中存在,则返回值为集合中键所对应的值(该值为替换之前的值),并把指定的键所对应的值替换成指定的新值。
Map集合遍历方式
键找值方式:即通过元素中的键,获取对应的值
步骤
1.获取map中所有的键,由于键是唯一的,所以返回一个Set集合
2.遍历键的Set集合,获取到每一个键
3.根据键,获取键所对应的值
代码:
在上述代码中添加以下代码:
//获取所有键的set集合
Set<String> keys = map.keySet();
//遍历集合 得到每一个键
for(String key:keys){
//通过键找值
String value = map.get(key);
System.out.println(key+"的cp是"+value);
}
Entry键值对对象
我们已经知道,Map中存放的是两种对象,一个是key一个是value,他们在map中是一一对应的关系,这一对对象又被称为Map中的一个entry,entry将键值对的对应关系封装成了对象,即键值对对象。这样我们在遍历Map集合的时候,就可以从每一个价值对对象中获取到对应的键和值。
既然Entry表示一对键和值,那么同样也提供了获取对应的键和值的方法
- public K getKey() 获取entry对象的键
- public V getValue() 获取Entry对象的value
在map集合中也提供了获取所有的Entry对象的方法:
public Set> entrySet() 获取map集合中所有的键值对对象的set集合
键值对对象方式遍历集合
键值对方式:即通过集合中每个键值对对象,获取键值对对象的键和值。
步骤
1.获取map集合中所有的键值对对象,以set集合的形式返回
2.遍历包含键值对对象的set集合,得到每一个键值对对象
3.根据键值对对象提供的方法获取对应的键和值
代码示例:
//创建Map对象
HashMap<String, String> map = new HashMap<>();
//添加元素到集合
map.put("黄晓明","杨颖");
map.put("文章","马伊利");
map.put("谢霆锋","张柏芝");
map.put("王宝强","马蓉");
//获取所有键值对对象的set集合
Set<Map.Entry<String, String>> entrySet = map.entrySet();
//遍历得到每一个entry
for(Map.Entry<String,String> entry:entrySet){
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key+"的cp是"+value);
}
注意:
map集合不能直接使用迭代器或者foreach循环进行遍历,但是转成set集合后就可以使用了
hashMap存储自定义类型的键
定义一个学生类(姓名,年龄),都有自己的家庭住址,那么既然又对应的关系,则将学生对象和家庭住址存储到map集合中
学生作为键,家庭住址作为值,注意:学生姓名相同,并且年龄相同视为同一学生。
当给HashMap中存放自定义对象时,如果自定义对象作为Key存在,这是需要保证对象唯一,必须复写对象的hashCode和equals方法。
代码演示:
public static void main(String[] args) {
//创建hashMap对象
HashMap<Student, String> map = new HashMap<>();
//添加元素
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(null,"南京");
map.put(null,"xi京");
System.out.println(map);
//取出元素 键找值方式
/*Set<Student> keySet = map.keySet();
for(Student key:keySet){
String value = map.get(key);
System.out.println(key.toString()+"=========="+value);
}*/
}
注意:
map集合中的键如果是自定义类型,需要重写hashCode方法和equals方法。
map集合中的键可以允许为null,并且只允许有一个。
LinkedHashMap
我们知道hashMap保证成对元素唯一,并且查询速度很快,可是成对元素存放进去是没有顺序的,那么我们要保证有序,还要速度快怎么办?在hashMap下面有个子类,linkedHashMap,它是哈希表+链表组合的一个数据存储结构。
代码示例:
public class LinkedHashMapDemo {
public static void main(String[] args) {
LinkedHashMap<String, String> map = new LinkedHashMap<>();
map.put("邓超","孙俪");
map.put("刘德华","朱丽倩");
map.put("周杰伦","昆凌");
Set<Map.Entry<String, String>> entrySet = map.entrySet();
for(Map.Entry<String,String> entry:entrySet){
System.out.println(entry.getKey()+"--------"+entry.getValue());
}
}
}
Map课堂练习:
题目:计算一个字符串中每个字符出现的次数
分析:
1.获取一个字符串对象(利用scanner)
2.创建一个集合对象,key是出现的字符,value是出现的次数
3.遍历字符串,获取每一个字符,往map集合中添加
4.判断map中是否有该键
5.如果没有,第一次出现,存储次数为1,如果有,则说明已经出现过,获取之前的值进行++,再次存储
6.打印结果
public class JiShu {
public static void main(String[] args) {
System.out.println("请输入一个字符串:");
String line = new Scanner(System.in).next();
findChar(line);
}
public static void findChar(String line){
//创建一个集合 用来存储字符出现的次数
HashMap<Character, Integer> map = new HashMap<>();
//遍历字符串
for(int i=0;i<line.length();i++){
char c = line.charAt(i);
//判断该字符是否在字符串中出现过
if(!map.containsKey(c)){
//说明这个字符没有出现过 第一次
map.put(c,1);
}else {
//说明之前出现过 要获取之前的次数
Integer count = map.get(c);
//递增再次存入
map.put(c,++count);
}
}
System.out.println(map);
}
}