一文搞懂Map初始化与赋值,码农必备!

2025-01-10 10:01:10

一、Map 是啥?为啥要用它?

图片8.jpg

在编程的世界里,Map 就像是一个超级收纳箱,它是一种用来存储数据的结构。和普通的数组、列表不一样,Map 存储的是一对一对的 “键值对”,简单来说,就是每个数据都有一个对应的 “标签”,通过这个 “标签”(也就是键),我们能快速找到它所对应的 “内容”(也就是值)。比如说,咱们要存储一个班级学生的成绩,用数组的话,可能就是 [90, 85, 92, 78……],但这样很难直接看出哪个成绩对应哪个学生。要是用 Map,就可以像这样:{"小明": 90, "小红": 85, "小刚": 92……},一目了然,通过学生的名字(键)就能马上拿到他们的成绩(值)。再比如电商平台管理商品信息,商品名称作为键,商品的价格、库存、描述等详情作为值,不管是查询还是更新某个商品的信息,都能迅速定位,高效便捷。这就是 Map 的强大之处,它让数据的管理和查找变得井井有条,极大地提升了编程处理数据的效率,能帮我们轻松应对各种复杂的信息存储需求。

二、初始化 Map 的几种常见方式

(一)使用 put () 方法逐个添加键值对

这是最基础、最直观的一种方式。咱们先创建一个 Map 对象,通常用得比较多的是 HashMap,就像这样:Map<String, Integer> map = new HashMap<>(); 这里<String, Integer> 表示这个 Map 里的键是字符串类型,值是整数类型。创建好之后,就可以用 put() 方法一个一个地把键值对往里塞啦,比如:这样就创建了一个简单的存储水果数量的 Map,键是水果名称,值是对应的数量。这种方式虽然简单直接,容易理解,但是如果要初始化的键值对特别多,那代码就会显得很冗长,看着眼花缭乱,而且一个个敲也容易出错。

(二)使用静态代码块初始化 Map

静态代码块是在类加载的时候就执行的,而且只会执行一次,特别适合用来初始化那些固定不变的键值对。还是拿刚才水果数量的例子,代码可以写成这样:对比一下前面用 put() 方法一个个添加的方式,这里是不是简洁多了?所有的初始化操作都在静态代码块里一次性搞定,代码结构清晰,一目了然,别人看你的代码时也能很快明白这些初始数据是干啥的。不过要注意哦,因为静态代码块只在类加载时执行一次,所以如果后续运行过程中需要动态地改变 Map 里的数据,这种方式就不太合适了,它更侧重于一开始就固定好的那些配置信息之类的初始化。

(三)使用双括号初始化(匿名内部类)

这种方式有点小 “神奇”,看起来很简洁。还是以存储数据为例,假设我们要存储几个城市的人口数量,代码可以这么写:这里外层的大括号是创建 HashMap 的实例,内层的双括号 {{}} 其实是创建了一个匿名内部类,在这个匿名内部类的初始化块里用 put() 方法添加键值对。这种写法让代码非常紧凑,在一些简单场景下看起来很清爽,一眼就能看清初始化的数据。但是呢,它也有一些 “坑”。因为匿名内部类会持有外部类的引用,如果不小心,当外部类生命周期结束了,而这个匿名内部类还被 Map 引用着,就可能导致内存泄漏。而且在涉及到序列化、反序列化的时候,也容易出现问题,比如可能会串行化失败,导致数据保存或读取不正常。所以用这种方式的时候得谨慎,要是对内存、序列化这些方面要求高,或者不确定后续会不会有坑,还是考虑前面更稳妥的初始化方法。

三、Java 9 + 带来的新玩法

Java 9 可是给我们带来了一些新的 “神器”,让 Map 的初始化更加得心应手。其中最亮眼的就是 Map.of() 和 Map.ofEntries() 方法。先看看 Map.of(),假设我们要创建一个存储几个颜色对应英文单词的 Map,代码可以写成这样:Map<String, String> colorMap = Map.of("红色", "red", "绿色", "green", "蓝色", "blue"); 短短一行代码,就把 Map 初始化好了,是不是超级简洁?它的参数是有上限的,最多只能 20 个参数,也就是 10 个键值对,而且不允许有重复的键。这就像是给我们准备了一个便捷的小工具包,适合那些键值对数量固定又不多,并且键不能重复的场景,比如一些配置信息、常量映射等,用它来初始化,代码清爽,一眼就能看清数据结构。再说说 Map.ofEntries(),它接受一个 Map.Entry 对象的可变参数。比如说,我们有这样一组员工姓名和工号的数据:这种方式就灵活多了,参数数量可以是任意的,虽然也不允许重复键,但对于需要一次性初始化较多键值对,或者是从其他数据结构转换过来的场景,就特别合适。它就像是一把万能钥匙,打开了复杂数据初始化的大门,让我们可以根据实际情况自由组合键值对,轻松构建出符合需求的 Map。和以前的初始化方式相比,这两个新方法省去了创建对象、调用 put() 方法等繁琐步骤,让代码更加简洁高效,是咱们 Java 程序员在处理 Map 初始化时的得力助手。

四、Guava 库中的 ImmutableMap

除了 Java 自带的那些初始化 Map 的方法,Guava 库也为我们提供了超好用的工具,那就是 ImmutableMap。它创建出来的 Map 可是 “铁打的”,一旦创建,就别想修改里面的数据了,绝对的 “只读” 模式。比如说,我们要存储一些系统的配置信息,像数据库连接的各种参数:用户名、密码、连接地址、端口号等,这些信息在系统运行过程中肯定是不能变的。代码就可以这么写:这里用 ImmutableMap.of() 方法轻松创建了一个不可变的 Map 来存储数据库配置,在程序的任何地方都无法修改它,保证了配置的稳定性和一致性,防止误操作带来的风险。要是需要初始化的数据量比较大,还可以用 ImmutableMap.builder() 来构建,就像这样:通过 builder() 模式,一个一个地添加键值对,最后调用 build() 方法生成不可变 Map,这种方式在处理大量数据时更加灵活、易读,而且不用担心数据被篡改,为程序的稳定性保驾护航,特别适用于那些作为常量、配置信息的 Map 场景,让代码更加健壮可靠。

五、不同方式大比拼

这么多种初始化和赋值 Map 的方法,到底啥时候用哪种呢?咱们来详细对比一下。先看代码简洁度,使用 Map.of()(Java 9+)和双括号初始化(匿名内部类)的方式在简单场景下代码很简洁,一行或者几行就能搞定,看起来清爽。像 Map<String, String> colorMap = Map.of("红色", "red", "绿色", "green", "蓝色", "blue"); ,一目了然。而使用 put() 方法逐个添加就显得啰嗦,要是键值对多,一堆 put() 语句,看着眼花缭乱。静态代码块比 put() 方法稍好一点,起码集中在一起,不过也不如前两者简洁。Guava 库的 ImmutableMap.of() 用于少量固定数据也很简洁, ImmutableMap.builder() 在数据量较大时,结构清晰,也有不错的简洁度。执行效率方面,一般来说,简单的 put() 方法逐个添加和静态代码块初始化效率相对稳定,因为就是常规的操作。双括号初始化(匿名内部类)由于涉及匿名内部类的创建等额外开销,执行效率会稍低一点。有测试在创建大量 Map 对象时,它比普通 put() 方法慢个 10% - 15% 左右。而 Java 9 + 的 Map.of() 和 Map.ofEntries() 方法内部做了优化,效率挺高,和常规方式不相上下,甚至在一些场景下还更快,因为减少了不必要的对象创建步骤。Guava 库的 ImmutableMap 在创建后由于不可变,避免了一些潜在的修改冲突检查等开销,对于作为常量使用的 Map,效率也很不错。内存占用上,Map.of() 这种创建不可变小 Map 的方式,因为内部优化,占用内存相对少,尤其是键值对不多的时候。双括号初始化(匿名内部类)由于匿名内部类的存在,以及可能引发的外部类引用持有问题,容易造成额外的内存占用,在大规模使用或者对象生命周期复杂时,可能出现内存泄漏风险,隐患较大。静态代码块和普通 put() 方法初始化的 Map,内存占用正常,就是常规对象的开销。Guava 库的 ImmutableMap 因为不可变,在内存管理上有优势,不会有额外的动态扩容等内存波动,对于配置信息这种长期占用内存的场景,很节省空间。适用场景的话,如果是简单的临时数据存储,少量键值对且后续可能修改,用 put() 方法就行,方便灵活。要是固定不变的配置信息,像系统参数、常量映射,Map.of()(键值对少)、Map.ofEntries()(键值对可多)或者 Guava 库的 ImmutableMap 就很合适,保证数据不可变,防止误改。静态代码块适合初始化那些类加载时就固定的、与类紧密相关的 Map 数据,比如一些类的静态配置。双括号初始化(匿名内部类),只建议在简单、临时、对内存和序列化没严格要求,追求代码短期简洁的小场景下用用,要是涉及复杂业务、多线程、序列化反序列化,就尽量避开,免得踩坑。咱们今儿个一起深入探讨了初始化 Map 并赋值的多种方法,从最基础的 put() 方法,到静态代码块、双括号初始化,再到 Java 9 + 带来的便捷新特性,还有 Guava 库的 ImmutableMap,各有千秋。大家在实际编程的时候,一定要根据项目的具体需求,像是数据量大小、是否可变、对执行效率和内存占用的敏感度等来综合考量,选出最顺手、最能让代码 “闪闪发光” 的那种初始化方式。别小瞧这一点,代码写得好,后续维护、扩展都轻松不少,说不定还能帮你提前发现潜在的 bug 呢!希望大家都动手试试这些方法,把它们融入到自己的代码 “武器库” 中。之后呢,咱们还会分享更多实用的编程技巧、知识干货,记得持续关注,一起在编程的道路上升级打怪,写出更牛的代码!


声明:此篇为墨韵科技原创文章,转载请标明出处链接: https://www.360jidan.com/news/4714.html
  • 网站建设
  • SEO
  • 信息流
  • 短视频
合作伙伴
在线留言
服务热线

服务热线

15879069746

微信咨询
返回顶部
在线留言