Java Map 初始化及其他

Java双括号初始化
本文解析了Java中双括号初始化语法的原理及其在集合初始化中的应用,并通过示例对比了传统方法与双括号初始化的区别。

初看 cgaolei 翻译的 Java技巧之双括弧初始化 一文,走马观花,只知用法,未细看后面的解释。蔚为惊艳,心里想 Java 竟然有这么神奇的语法而一直未得知。因为在初始化集合时确实方便不少。原来做某些测试要初始化集合时会用到 commons-lang 包和 JDK 的 Arrays 工具类,现在知道可以这么用了:

 

01. Map map = new HashMap() {
02.          put( "Name" , "Unmi" ); 
03.          put( "QQ" , "1125535" ); 
04. }}; 
05.   
06. List stooges = new ArrayList() {
07.          add( "Larry" ); 
08.          add( "Moe" ); 
09.          add( "Curly" ); 
10. }}; 
 
看起来都是在一条语句里完成,而不需要分步骤写成:

 

1. Map map = new HashMap(); 
2. map.put( "Name" , "Unmi" ); 
3. map.put( "QQ" , "1125535" );


一不小心没好好理解的人可能以为它是什么特别的语法,关键是大括号连一块了,原作者也是在故作姿态,美其名曰:双括弧语法(double-brace syntax)。真是乱花渐欲迷人眼,其实就是匿名类加初始块。该文有解释:第一层括弧 实际是定义了一个内部匿名类 (Anonymous Inner Class),第二层括弧 实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。

那怎么去更好理解它呢?如果我们写成如下的方式应该会更好理解吧,提个技巧,在 Eclipse 中对第一段代码按下 Ctrl + Shift + F 就如下了:

 

1. Map map = new HashMap() { 
2.      { 
3.          put( "Name" , "Unmi" ); 
4.          put( "QQ" , "1125535" ); 
5.      } 
6. };

其实就是匿名类啊,会创建出一个 HashMap 的子类来,匿名类中一个 {} 括起来的初始化块,里面自然可放置初始化代码。{} 块中的代码编译后会放到 <init>(),也就是构造方法中去,所以可用来初始化实例。如果是写在 TestDoubleBrace 类中,编译后你会看到会生成 TestDoubleBrace$1.class 文件,反编译该文件内容是:

 

01. final class com.unmi.TestDoubleBrace$1 extends java.util.HashMap{ //创建了一个 HashMap 的子类 TestDoubleBracke$1 
02. com.unmi.TestDoubleBrace$1(); 
03.    Code: 
04.     0:   aload_0 
05.     1:   invokespecial   #8; //Method java/util/HashMap."<init>":()V   //{} 中的代码放到了构造方法中去了 
06.     4:   aload_0 
07.     5:   ldc     #10; //String Name 
08.     7:   ldc     #12; //String Unmi 
09.     9:   invokevirtual   #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 
10.     12:  pop 
11.     13:  aload_0 
12.     14:  ldc     #18; //String QQ 
13.     16:  ldc     #20; //String 1125535 
14.     18:  invokevirtual   #14; //Method put:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object; 
15.     21:  pop 
16.     22:  return 
17.   
18. }


所以说白了,什么双括弧语法啊,就是代码写得不规范,才使得那么的令人费解。如果还不能理解,再列两个惯用代码来:

 

01. JFrame frame = new JFrame(); 
02. frame.addMouseListener( new MouseAdapter() { 
03.      public void mouseClicked(MouseEvent e) { 
04.          // do womething here. 
05.      } 
06. }); 
07.   
08. Thread thread = new Thread() {{ // 也学着样把大括号也连一块写了 
09.          this .setName( "作业处理线程" ); 
10.      } // 如果不重新定义 run() 方法,那么后面那个大括号也能与这个并一块 
11.   
12.      public void run() { 
13.          // do something here. 
14.      } 
15. }; 
16. thread.start();


应该没问题了吧,上面是事件监听器和多线程常用的写法,如果他不把大括号连在一起,而是规范的写代码,相信您一开始也不会对所谓的 Double Brace Syntax 有太多的困惑。要说这种初始化方法运用到集合中还挺方便的,只是无端的多了些匿名类。

刚开始我看到这种双括符写法也是把它奉若圣经,对它只一知半解,昨天在用 XStream 把一个对象生成 XML 文件时,其中有一个 List 属性,我就借用了这种双括符法来初始化元素,结果生成的 XML 文件走了样,原因是 XStream 的 Converter 能处理 ArrayList,但无法很好的处理生成的 ArrayList 的匿名子类。因此才回头认真的重新审视了一番这个所谓的双括符初始化语法。

 

### JavaMap初始化方法 #### 新建Map对象并手动填充数据 通过创建`HashMap<String, String>`实例来构建一个名为`myMap`的地图,并利用静态代码块中的`put()`函数向其中加入键值对[^1]。 ```java public class Demo { private static final Map<String, String> myMap = new HashMap<>(); static{ myMap.put("key1", "value1"); myMap.put("key2", "value2"); } } ``` #### 使用双括号语法(匿名内部类) 这种方式是在定义的同完成赋值操作,适用于不需要对外暴露修改权限的情况。它基于匿名内部类实现,在大括号内可以直接调用`put`方法[^4]。 ```java Map<String, Integer> map = new HashMap<>() {{ put("one", 1); put("two", 2); }}; ``` #### 利用Java 9引入的简化构造器 自JDK 9起支持更简洁的方式来声明不可变映射表——即那些一旦被设定就不能再更改其内容的数据结构。这不仅使代码更加紧凑易读,而且还能提高程序的安全性和性能。 ```java import java.util.Map; // 创建带有两个条目的只读视图 Map<String, Long> readOnlyMap = Map.of( "apple", 3L, "banana", 2L); // 如果需要更多元素,则可采用ofEntries()形式 Map<String, Long> largerReadOnlyMap = Map.ofEntries( Map.entry("apple", 3L), Map.entry("banana", 2L), Map.entry("orange", 5L)); ``` #### 借助第三方库Guava提供的工具类 除了标准API外,Google Guava等外部依赖项也提供了便捷的方法用于快速建立哈希表或其他类型的关联数组。这些额外的功能往往能够满足特定场景下的需求。 ```java import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; // 构造ImmutableMap ImmutableMap<String, Integer> immutableExample = ImmutableMap.<String, Integer>builder() .put("first", 10) .put("second", 20).build(); // 或者使用Maps.newLinkedHashMap()等其他实用工厂方法 Map<String, Double> linkedHashMapExample = Maps.newLinkedHashMap(); linkedHashMapExample.put("pi", Math.PI); linkedHashMapExample.put("euler", Math.E); ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值