Java中HashMap的初始化:“字面量”方式的秘密

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

如何初始化Java中的HashMap而不抓狂:面向新手的完整解析

\n\n

你是否曾在编写Java代码时,觉得为了创建一个简单的字典需要写出一整篇“史诗”?尤其是当你希望像Python或JavaScript那样写得既优雅又简洁的时候。感同身受吗?在Stack Overflow上,关于如何以字面量方式初始化HashMap的问题获得了数千次浏览。这并非偶然。

\n\n

在本文中,我们将全面解析所有合法的Java中HashMap初始化方式,从经典方法到现代方法,并附有代码示例和面向初学者的解释。你将了解如何用一行代码填充Map,何时使用Map.of(),以及为什么双大括号初始化是一把双刃剑。

\n\n

为什么简单地“放入”元素会让人头疼?

\n\n

想象一下,你需要创建一个包含三对“键-值”的HashMap。新手典型的代码如下:

\n\n
HashMap<String, Integer> map = new HashMap<>();\nmap.put("apple", 5);\nmap.put("banana", 3);\nmap.put("orange", 7);
\n\n

看起来还行,但当你有十个这样的Map时,代码就会变得冗长。你肯定想要简洁,对吧?在Python中,一行代码就能搞定:dict = {"apple": 5, "banana": 3}。那么在Java中呢?剧透:有几种方法,我们现在就来逐一分析。

\n\n

方法一:双大括号初始化

\n\n

最流行(也最具争议)的方法是双大括号初始化。它看起来像这样:

\n\n
HashMap<String, Integer> map = new HashMap<>() {{\n    put("apple", 5);\n    put("banana", 3);\n    put("orange", 7);\n}};
\n\n

它是如何工作的?第一对大括号创建了一个继承自HashMap的匿名内部类。第二对大括号是实例初始化块,在创建对象时执行。里面的所有内容都是对put()的调用。

\n\n

优点:

\n
    \n
  • 代码变得更紧凑、更易读。
  • \n
  • 无需编写多行put()代码。
  • \n
\n\n

缺点(而且很多):

\n
    \n
  • 性能:每次都会创建一个匿名类。这给JVM增加了额外负担。
  • \n
  • 内存:匿名类持有对外部类的引用,可能导致内存泄漏。
  • \n
  • 序列化:如果你尝试序列化这样的Map,可能会出现问题。
  • \n
  • 不兼容性:某些框架(例如某些版本的Gson)无法正常工作。
  • \n
\n\n

结论:这种方法可行,但最好只在测试代码或个人项目中使用。不推荐用于生产环境。

\n\n

方法二:Guava(Google的库)

\n\n

如果你使用Google Guava(这是一个非常流行的库),那么问题可以优雅地解决:

\n\n
import com.google.common.collect.ImmutableMap;\n\nMap<String, Integer> map = ImmutableMap.of(\n    "apple", 5,\n    "banana", 3,\n    "orange", 7\n);
\n\n

特点:

\n
    \n
  • 创建一个不可变的Map。
  • \n
  • of()方法针对0到5对键值进行了重载。如果更多,请使用ImmutableMap.builder()。
  • \n
  • 非常适合配置和静态数据。
  • \n
\n\n

缺点:需要引入外部依赖。如果项目已经在使用Guava,那很好;如果没有,可能得不偿失。

\n\n

方法三:Java 9+ — Map.of() 和 Map.ofEntries()

\n\n

从Java 9开始,标准库中引入了M

博客

书籍推荐