J2EE 快速入门之第三章 Map集合讲解

一:Map接口介绍

              Map接口提供了一种映射关系,其中的内容都是以键 key value 对的形式存储的
public interface Map<K,V> {
}
K和V都是泛型 其中K指的是键的类型 V指的是值的类型
        在初始化 Map 方法的时候需要指定这两个泛型
        提醒 :不指定则默认为 Object
Map m1=new HashMap(); //键值都为Object类型
Map<String,String> m2=new HashMap<String,String>(); //键值都为String类型
  • 键值对解释

           从生活中的案例下手:国家简称  

                 Japan( 日本 )
                 China( 中国 )
                 Germany( 德国 )
                 France( 法国 )
考虑到某些问题,于是对每个国家的名字进行了缩写
               JP -- Japan( 日本 )
               CN -- China( 中国 )
                DE -- Germany( 德国 )
                FR -- France( 法国 )
从案例中带入,突出 Map 键值对的以下特点
          ① 键与值相对应(互相绑定)
                  JP 对应的就是 Japan , 这里将 JP 理解为键,那么对应的 Japan 就是值
          ② 键不能重复
                  对于世界而言,不会出现两个相同的国家简称

二:Map方法介绍

   使用代码完成上方的国家简称案例
  • 分析,得到键值的类型都为String,初始化Map集合
Map<String,String> ms=new HashMap<String,String>();
  • 往集合中添加上面的案例数据 map.put(K,V)
ms.put("JP", "Japan");
ms.put("CN", "China");
ms.put("DE", "Germany");
ms.put("FR", "Franch");
讲解 put 方法:
             往 Map 中添加键值对数据,并且是根据键来存放值,形成一对一的关系
存入时会碰到以下情况:
  • 如果键在集合中不存在这个键,就是向集合中添加这个键值对
  •  如果键在集合中已经存在了,就会用这个键值对替换原来的值
在以上案例新增代码
ms.put("JP", "hello");
System.out.println("添加之后的长度:"+ms.size());

输出结果:
              添加之后的长度 :4
  • 查看简称为 CN 的国家 map.get()
     使用对应的键:
System.out.println("CN对应的国家:"+ms.get("CN"));
输出结果:
             CN 对应的国家 :China
  • 提出问题:如果被消灭了? map.remove()
需要在集合中移除对应的键 key :
ms.remove("JP");
System.out.println("移除之后的长度:"+ms.size());

输出结果:
 
ms.remove("JP");
System.out.println("移除之后的长度:"+ms.size());

  • 查看当前集合中的元素,数据遍历操作
Map 集合中保存着两组值,一组用于保存 Map 的键 key ,另一组保存着 Map 的值 value

 

key 不能重复的原因: 使用的是 Set 集合
如果需要遍历数据,我们使用 map.keySet() 来获得所有的键

 

Set<String> ks = ms.keySet();
  • 遍历ks,然后在根据key拿到对应的value: 
输出结果:
       提问:能不能直接拿到值?是不是也用一个 Set 集合装了所有的值?

for (String s : ks) {
// s是key
// 还需要调用get方法 拿到对应的value
System.out.println("键:"+s+"--值"+ms.get(s));
}
输出结果:
              键 :DE-- Germany
              键 :JP-- Japan
              键 :CN-- China
              键 :FR-- Franch
提问:能不能直接拿到值?是不是也用一个 Set 集合装了所有的值?
         可以通过 values() 拿到所有的值,但不是 Set 集合,因为值是可以重复的

 

代码演示:
Collection<String> vs = ms.values();
for (String v : vs) {
System.out.println("值:"+v);
}

输出结果 :
                   值 :Germany
                   值 :Japan
                   值 :China
                   值 :Franch
  • 使用 Entry 遍历
Map 中包括一个内部类 Entry, 该类封装一个键值对

interface Entry<K,V> {
Object getKey(); 返回该Entry里包含的key值;
Object getvalue(); 返回该Entry里包含的value值;
Object setValue(V value); 设置该Entry里包含的value值,并设置新的value值
}

 

代码演示:
Set<Entry<String, String>> es = ms.entrySet();
for (Entry<String, String> e : es) {
//e相当于一行数据 既包含key 也包含value
System.out.println("键:"+e.getKey()+"--值"+e.getValue());
}
输出结果:
                 键 :DE-- Germany
                 键 :JP-- Japan
                 键 :CN-- China
                 键 :FR-- Franch

三:Map接口下的实现类

  • HashMapuHashTable
哈希表(散列表)
哈希表结构解读请看下一篇博客
HashMap Hashtable 的关系完全类似于 ArrayList Vector 的关系
HashTable 是线性安全的, HashMap 是线性不安全的,所以后者效率更高
HashTable 不允许使用 null 作为 key value ,否则会引发异常,而 HashMap 可以

 

哈希表是数组 + 链表的结合体 jdk1.8 之后加入了红黑树结构
数组的特点是:寻址容易,插入和删除困难
而链表的特点是:寻址困难,插入和删除容易
举例:
          手机上的通讯录,先根据姓氏分组(数组),每个姓氏对应一部分人(单向链表)
 

单向链表:
static class Node<K,V> implements Map.Entry<K,V> {
final int hash;
final K key;
V value;
Node<K,V> next;
}
  • TreeMap
        TreeMap 是一个有序的 key-value 集合,它是通过红黑树实现的,每个 key-value 对即作
为红黑树的一个节点。能够把它保存的记录根据键排序,默认是按键值的升序排序(自然顺
序),也可以指定排序的比较器,不允许 key 值为空,非同步的。

四:Map应用案例

  • 案例一(TreeMap)
1. 新建学生类:
public class Student {
private String name;
private int age;
}
2. Map 中放入 5 个学生, k= 学生对象, v= 学生地址
TreeMap<Student, String> ms=new TreeMap<Student, String>();
ms.put(new Student("小黑", 18), "北京");
ms.put(new Student("小白", 22), "湖南");
ms.put(new Student("小青", 15), "杭州");
ms.put(new Student("小绿", 30), "西北");
ms.put(new Student("小黑", 18), "伦敦");
3. 集合长度
System . out . println ( " 集合的长度 :" + ms . size ());
输出结果 :
    集合的长度 :5
    分析原因:Set集合中判断元素是否重复
4. 提出修改要求:只要名字和年龄相同认为是同一个学生
提问:重写 equals 还是 hashCode?
          两个都要重写,因为键是放在 Set 集合中( Set 集合的判断规则是 hashCode+equals 结合)
@Override
public int hashCode() {
return this.name.hashCode()+this.age;
}
@Override
public boolean equals(Object obj) {
...
}

执行之前的代码,输出结果:
            集合的长度 :4
5. 提出要求 : 输出所有的学生与对应的地址
Set<Entry<Student, String>> es = ms.entrySet();
for (Entry<Student, String> e : es) {
System.out.println(e);
}
输出结果 :
                Person [name= 小绿 , age=30]= 西北
                Person [name= 小青 , age=15]= 杭州
                Person [name= 小黑 , age=18]= 北京
                Person [name= 小白 , age=22]= 湖南
6. 提出要求:根据学生年龄大小来排序输出
           使用自然排序,让学生类实现 Comparable 接口,重写比较方法:
@Override
public int compareTo(Student o) {
return this.age-o.age;
}

输出结果:

                 Person [name= 小青 , age=15]= 杭州
                 Person [name= 小黑 , age=18]= 北京
                 Person [name= 小白 , age=22]= 湖南
                 Person [name= 小绿 , age=30]= 西北
  • 求字符串中字符的重复次数(HashMap)
1. 定义需要的 Map 集合
Map < String , Integer > ms = new HashMap < String , Integer > ();
2. 定义字符串
String str = "abca
3. 思路:
  • 每次得到将字符串中的第一个字符 a ,并记录当前字符长度 a1
  • 使用Stringreplace移除字符 a ,记录字符长度 a2
  • a1 - a2 即可得出当前字符的个数
  • 记录到map集合中
Map<String, Integer> ms=new HashMap<String, Integer>();
String str="abcdsdfhasfhjkehwkerggbgbmdfnbasnmfasdfklgasufweghuarbhasmfbs";
while(str.length()>0){//每次字符的长度会越来越短,如果为0就表示已经没有文字了
int a1=str.length();//未移除字符时的长度
String oldChar=str.charAt(0)+"";//得到当前字符串第一个字符
str=str.replace(oldChar, "");//从字符串中移除该字符
int a2=str.length();//移除狗的字符长度
ms.put(oldChar, a1-a2);//记录到map集合中
}
System.out.println(ms);
输出结果 :
           {a=7, b=6, c=1, d=4, e=3, f=7, g=5, h=5, j=1,k=3, l=1, m=3, n=2, r=2, s=7, u=2, w=2}
                     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值