阿里云-云小站(无限量代金券发放中)
【腾讯云】云服务器、云数据库、COS、CDN、短信等热卖云产品特惠抢购

使用Map

261次阅读
没有评论

共计 3981 个字符,预计需要花费 10 分钟才能阅读完成。

我们知道,List是一种顺序列表,如果有一个存储学生 Student 实例的 List,要在List 中根据 name 查找某个指定的 Student 的分数,应该怎么办?

最简单的方法是遍历 List 并判断 name 是否相等,然后返回指定元素:

List<Student> list = ...
Student target = null;
for (Student s : list) {if ("Xiao Ming".equals(s.name)) {
        target = s;
        break;
    }
}
System.out.println(target.score);

这种需求其实非常常见,即通过一个键去查询对应的值。使用 List 来实现存在效率非常低的问题,因为平均需要扫描一半的元素才能确定,而 Map 这种键值(key-value)映射表的数据结构,作用就是能高效通过 key 快速查找value(元素)。

Map 来实现根据 name 查询某个 Student 的代码如下:

import java.util.HashMap;
import java.util.Map;

public class Main {public static void main(String[] args) {Student s = new Student("Xiao Ming", 99);
        Map<String, Student> map = new HashMap<>();
        map.put("Xiao Ming", s); // 将 "Xiao Ming" 和 Student 实例映射并关联
        Student target = map.get("Xiao Ming"); // 通过 key 查找并返回映射的 Student 实例
        System.out.println(target == s); // true,同一个实例
        System.out.println(target.score); // 99
        Student another = map.get("Bob"); // 通过另一个 key 查找
        System.out.println(another); // 未找到返回 null
    }
}

class Student {public String name;
    public int score;
    public Student(String name, int score) {this.name = name;
        this.score = score;
    }
}

通过上述代码可知:Map<K, V>是一种键 - 值映射表,当我们调用 put(K key, V value) 方法时,就把 keyvalue做了映射并放入 Map。当我们调用V get(K key) 时,就可以通过 key 获取到对应的 value。如果key 不存在,则返回 null。和List 类似,Map也是一个接口,最常用的实现类是HashMap

如果只是想查询某个 key 是否存在,可以调用 boolean containsKey(K key) 方法。

如果我们在存储 Map 映射关系的时候,对同一个 key 调用两次 put() 方法,分别放入不同的value,会有什么问题呢?例如:

import java.util.HashMap;
import java.util.Map;

public class Main {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();
        map.put("apple", 123);
        map.put("pear", 456);
        System.out.println(map.get("apple")); // 123
        map.put("apple", 789); // 再次放入 apple 作为 key,但 value 变为 789
        System.out.println(map.get("apple")); // 789
    }
}

重复放入 key-value 并不会有任何问题,但是一个 key 只能关联一个 value。在上面的代码中,一开始我们把key 对象 "apple" 映射到 Integer 对象 123,然后再次调用put() 方法把 "apple" 映射到 789,这时,原来关联的value 对象 123 就被“冲掉”了。实际上,put()方法的签名是 V put(K key, V value),如果放入的key 已经存在,put()方法会返回被删除的旧的value,否则,返回null

始终牢记

Map 中不存在重复的 key,因为放入相同的 key,只会把原有的 key-value 对应的 value 给替换掉。

此外,在一个 Map 中,虽然 key 不能重复,但 value 是可以重复的:

Map<String, Integer> map = new HashMap<>();
map.put("apple", 123);
map.put("pear", 123); // ok

遍历 Map

Map 来说,要遍历 key 可以使用 for each 循环遍历 Map 实例的 keySet() 方法返回的 Set 集合,它包含不重复的 key 的集合:

import java.util.HashMap;
import java.util.Map;

public class Main {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();
        map.put("apple", 123);
        map.put("pear", 456);
        map.put("banana", 789);
        for (String key : map.keySet()) {Integer value = map.get(key);
            System.out.println(key + "=" + value);
        }
    }
}

同时遍历 keyvalue可以使用 for each 循环遍历 Map 对象的 entrySet() 集合,它包含每一个 key-value 映射:

import java.util.HashMap;
import java.util.Map;

public class Main {public static void main(String[] args) {Map<String, Integer> map = new HashMap<>();
        map.put("apple", 123);
        map.put("pear", 456);
        map.put("banana", 789);
        for (Map.Entry<String, Integer> entry : map.entrySet()) {String key = entry.getKey();
            Integer value = entry.getValue();
            System.out.println(key + "=" + value);
        }
    }
}

MapList 不同的是,Map存储的是 key-value 的映射关系,并且,它 不保证顺序 。在遍历的时候,遍历的顺序既不一定是put() 时放入的 key 的顺序,也不一定是 key 的排序顺序。使用 Map 时,任何依赖顺序的逻辑都是不可靠的。以 HashMap 为例,假设我们放入 "A""B""C" 这 3 个 key,遍历的时候,每个key 会保证被遍历一次且仅遍历一次,但顺序完全没有保证,甚至对于不同的 JDK 版本,相同的代码遍历的输出顺序都是不同的!

注意

遍历 Map 时,不可假设输出的 key 是有序的!

练习

请编写一个根据 name 查找 score 的程序,并利用 Map 充当缓存,以提高查找效率:

import java.util.*;

public class Main {public static void main(String[] args) {
        List<Student> list = List.of(new Student("Bob", 78),
            new Student("Alice", 85),
            new Student("Brush", 66),
            new Student("Newton", 99));
        var holder = new Students(list);
        System.out.println(holder.getScore("Bob") == 78 ? "测试成功!" : "测试失败!");
        System.out.println(holder.getScore("Alice") == 85 ? "测试成功!" : "测试失败!");
        System.out.println(holder.getScore("Tom") == -1 ? "测试成功!" : "测试失败!");
    }
}

class Students {
    List<Student> list;
    Map<String, Integer> cache;

    Students(List<Student> list) {this.list = list;
        cache = new HashMap<>();}

    /**
     * 根据 name 查找 score,找到返回 score,未找到返回 -1
     */
    int getScore(String name) {// 先在 Map 中查找:
        Integer score = this.cache.get(name);
        if (score == null) {// TODO:
        }
        return score == null ? -1 : score.intValue();}

    Integer findInList(String name) {for (var ss : this.list) {if (ss.name.equals(name)) {return ss.score;
            }
        }
        return null;
    }
}

class Student {
    String name;
    int score;

    Student(String name, int score) {this.name = name;
        this.score = score;
    }
}

下载练习

小结

Map是一种映射表,可以通过 key 快速查找value

可以通过 for each 遍历 keySet(),也可以通过for each 遍历entrySet(),直接获取key-value

最常用的一种 Map 实现是HashMap

正文完
星哥玩云-微信公众号
post-qrcode
 0
星锅
版权声明:本站原创文章,由 星锅 于2024-08-05发表,共计3981字。
转载说明:除特殊说明外本站文章皆由CC-4.0协议发布,转载请注明出处。
【腾讯云】推广者专属福利,新客户无门槛领取总价值高达2860元代金券,每种代金券限量500张,先到先得。
阿里云-最新活动爆款每日限量供应
评论(没有评论)
验证码
【腾讯云】云服务器、云数据库、COS、CDN、短信等云产品特惠热卖中

星哥玩云

星哥玩云
星哥玩云
分享互联网知识
用户数
4
文章数
19348
评论数
4
阅读量
7819761
文章搜索
热门文章
开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南

开发者必备神器:阿里云 Qoder CLI 全面解析与上手指南 大家好,我是星哥。之前介绍了腾讯云的 Code...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板1Panel:小白轻松构建Web服务与面板加固指南

云服务器部署服务器面板 1Panel:小白轻松构建 Web 服务与面板加固指南 哈喽,我是星哥,经常有人问我不...
我把用了20年的360安全卫士卸载了

我把用了20年的360安全卫士卸载了

我把用了 20 年的 360 安全卫士卸载了 是的,正如标题你看到的。 原因 偷摸安装自家的软件 莫名其妙安装...
星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛NAS-3:安装飞牛NAS后的很有必要的操作

星哥带你玩飞牛 NAS-3:安装飞牛 NAS 后的很有必要的操作 前言 如果你已经有了飞牛 NAS 系统,之前...
阿里云CDN
阿里云CDN-提高用户访问的响应速度和成功率
随机文章
飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛NAS中安装Navidrome音乐文件中文标签乱码问题解决、安装FntermX终端

飞牛 NAS 中安装 Navidrome 音乐文件中文标签乱码问题解决、安装 FntermX 终端 问题背景 ...
星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛NAS-6:抖音视频同步工具,视频下载自动下载保存

星哥带你玩飞牛 NAS-6:抖音视频同步工具,视频下载自动下载保存 前言 各位玩 NAS 的朋友好,我是星哥!...
每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年0.99刀,拿下你的第一个顶级域名,详细注册使用

每年 0.99 刀,拿下你的第一个顶级域名,详细注册使用 前言 作为长期折腾云服务、域名建站的老玩家,星哥一直...
Python自学26 – Cookie和Session

Python自学26 – Cookie和Session

Python 自学 26 – Cookie 和 Session 在学习 Web 开发时,Cooki...
星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

星哥带你玩飞牛NAS-16:飞牛云NAS换桌面,fndesk图标管理神器上线!

  星哥带你玩飞牛 NAS-16:飞牛云 NAS 换桌面,fndesk 图标管理神器上线! 引言 哈...

免费图片视频管理工具让灵感库告别混乱

一言一句话
-「
手气不错
星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛NAS-11:咪咕视频订阅部署全攻略

星哥带你玩飞牛 NAS-11:咪咕视频订阅部署全攻略 前言 在家庭影音系统里,NAS 不仅是存储中心,更是内容...
星哥带你玩飞牛NAS硬件03:五盘位+N5105+双网口的成品NAS值得入手吗

星哥带你玩飞牛NAS硬件03:五盘位+N5105+双网口的成品NAS值得入手吗

星哥带你玩飞牛 NAS 硬件 03:五盘位 +N5105+ 双网口的成品 NAS 值得入手吗 前言 大家好,我...
星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛NAS-12:开源笔记的进化之路,效率玩家的新选择

星哥带你玩飞牛 NAS-12:开源笔记的进化之路,效率玩家的新选择 前言 如何高效管理知识与笔记,已经成为技术...
你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你

你的云服务器到底有多强?宝塔跑分告诉你 为什么要用宝塔跑分? 宝塔跑分其实就是对 CPU、内存、磁盘、IO 做...
星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

星哥带你玩飞牛NAS-16:不再错过公众号更新,飞牛NAS搭建RSS

  星哥带你玩飞牛 NAS-16:不再错过公众号更新,飞牛 NAS 搭建 RSS 对于经常关注多个微...