Java学习者论坛

 找回密码
 立即注册

QQ登录

只需一步,快速开始

手机号码,快捷登录

恭喜Java学习者论坛(https://www.javaxxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,购买链接:点击进入购买VIP会员
JAVA高级面试进阶视频教程Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程

Go语言视频零基础入门到精通

Java架构师3期(课件+源码)

Java开发全终端实战租房项目视频教程

SpringBoot2.X入门到高级使用教程

大数据培训第六期全套视频教程

深度学习(CNN RNN GAN)算法原理

Java亿级流量电商系统视频教程

互联网架构师视频教程

年薪50万Spark2.0从入门到精通

年薪50万!人工智能学习路线教程

年薪50万!大数据从入门到精通学习路线年薪50万!机器学习入门到精通视频教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程 MySQL入门到精通教程
查看: 773|回复: 0

[Java基础知识]Java中HashMap初始化的另一种方式

[复制链接]
  • TA的每日心情
    开心
    2021-3-12 23:18
  • 签到天数: 2 天

    [LV.1]初来乍到

    发表于 2014-9-30 17:38:25 | 显示全部楼层 |阅读模式
    如果你接触过不同的语言,从语法和代码层面来说,java 是一种不折不扣的“臃肿、�嗦”的语言,从另一方面来说这种臃肿和�嗦也体现了它严谨的一面,作为适合构建大型、复杂项目的理由之一。 1、HashMap 初始化的文艺写法
        HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器。普通青年一般会这么初始化:

      HashMap<String, String> map =
            new HashMap<String, String>();
      map.put("Name", "June");
      map.put("QQ", "2572073701");

    看完这段代码,很多人都会觉得这么写太&#65533;嗦了,对此,文艺青年一般这么来了:
      HashMap<String, String> map =
            new HashMap<String, String>() {
       {
         put("Name", "June");
         put("QQ", "2572073701");
       }
      };
       
      
       
       

         
       

         
       
      
        嗯,看起来优雅了不少,一步到位,一气呵成的赶脚。然后问题来了,有童鞋会问:纳尼?这里的双括号到底什么意思,什么用法呢?哈哈,其实很简单,看看下面的代码你就知道啥意思了。
    1. public class Test {
    2.     /*private static HashMap< String, String> map = new HashMap< String, String>() {
    3.         {
    4.             put("Name", "June");
    5.             put("QQ", "2572073701");
    6.         }
    7.     };*/
    8.     public Test() {
    9.         System.out.println("Constructor called:构造器被调用");
    10.     }
    11.     static {
    12.         System.out.println("Static block called:静态块被调用");
    13.     }
    14.     {
    15.         System.out.println("Instance initializer called:实例初始化块被调用");
    16.     }
    17.     public static void main(String[] args) {
    18.         new Test();
    19.         System.out.println("=======================");
    20.         new Test();
    21.     }
    22. }
    复制代码
    输出:
      Static block called:静态块被调用
      Instance initializer called:实例初始化被调用
      Constructor called:构造器被调用
      =======================
      Instance initializer called:实例初始化被调用
      Constructor called:构造器被调用

    也就是说第一层括弧实际是定义了一个匿名内部类 (Anonymous Inner Class),第二层括弧实际上是一个实例初始化块 (instance initializer block),这个块在内部匿名类构造时被执行。这个块之所以被叫做“实例初始化块”是因为它们被定义在了一个类的实例范围内。
    上面代码如果是写在 Test 类中,编译后你会看到会生成 Test$1.class 文件,反编译该文件内容:
    D:eclipse_indigoworkspace_homeCDHJobsinpvuv>jad -p Test$1.class
    // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
    // Jad home page: http://www.kpdus.com/jad.HTML
    // Decompiler options: packimports(3)
    // Source File Name: Test.java package pvuv.zhaopin;
    import java.util.HashMap;
    // Referenced classes of package pvuv.zhaopin:
    // Test
       class Test$1 extends HashMap // 创建了一个 HashMap 的子类
      {
       Test$1()
       { // 第二个 {} 中的代码放到了构造方法中去了
         put("Name", "June");
        put("QQ", "2572073701");
       }
      } D:eclipse_indigoworkspace_homeCDHJobsinpvuv> 2、推而广之
       这种写法,推而广之,在初始化 ArrayList、Set 的时候都可以这么玩,比如你还可以这么玩:
      List<String> names = new ArrayList<String>() {
       {
         for (int i = 0; i < 10; i++) {
          add("A" + i);
         }
       }
      };
      System.out.println(names.toString()); // [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9]

    3、Java7:增加对 collections 的支持
    在 Java 7 中你可以像 Ruby, Perl、python 一样创建 collections 了。
    Note:这些集合是不可变的。 PS:由于原文[5]作者并没有标出 java 7 哪个小版本号引入的这些新特性,对于留言报错的同学,请尝试大于 1.7.0_09 或者 Java8 试试?
    1. List
    2.    list = new ArrayList
    3.   
    4.    ();
    5. list.add("item");
    6. String item = list.get(0);
    7. Set< String> set = new HashSet< String>();
    8. set.add("item");
    9. Map< String, Integer> map = new HashMap< String, Integer>();
    10. map.put("key", 1);
    11. int value = map.get("key");
    12. // 现在你还可以:
    13. List< String> list = ["item"];
    14. String item = list[0];
    15.                
    16. Set< String> set = {"item"};
    17.                
    18. Map< String, Integer> map = {"key" : 1};
    19. int value = map["key"];
    20.   
    复制代码
    4、文艺写法的潜在问题
         文章开头提到的文艺写法的好处很明显就是一目了然。这里来罗列下此种方法的坏处,如果这个对象要串行化,可能会导致串行化失败。
       1.此种方式是匿名内部类的声明方式,所以引用中持有着外部类的引用。所以当串行化这个集合时外部类也会被不知不觉的串行化,当外部类没有实现serialize接口时,就会报错。

    2.上例中,其实是声明了一个继承自HashMap的子类。然而有些串行化方法,例如要通过Gson串行化为json,或者要串行化为xml时,类库中提供的方式,是无法串行化Hashset或者HashMap的子类的,从而导致串行化失败。解决办法:重新初始化为一个HashMap对象:  new HashMap(map);
    这样就可以正常初始化了。

    5、执行效率问题
        当一种新的工具或者写法出现时,猿们都会来一句:性能怎么样?(这和男生谈论妹纸第一句一般都是:“长得咋样?三围多少?”一个道理:))
    关于这个两种写法我这边笔记本上测试文艺写法、普通写法分别创建 10,000,000 个 Map 的结果是 1217、1064,相差 13%。
    1. public class Test {
    2.     public static void main(String[] args) {
    3.         long st = System.currentTimeMillis();
    4.         /*
    5.         for (int i = 0; i < 10000000; i++) {
    6.             HashMap< String, String> map = new HashMap< String, String>() {
    7.                 {
    8.                     put("Name", "June");
    9.                     put("QQ", "2572073701");
    10.                 }
    11.             };
    12.         }
    13.         System.out.println(System.currentTimeMillis() - st); // 1217
    14.         */
    15.         for (int i = 0; i < 10000000; i++) {
    16.             HashMap< String, String> map = new HashMap< String, String>();
    17.             map.put("Name", "June");
    18.             map.put("QQ", "2572073701");
    19.         }
    20.         System.out.println(System.currentTimeMillis() - st); // 1064
    21.     }
    22. }
    复制代码
    6、由实例初始化块联想到的一些变量初始化问题
       从代码上看,a 为什么可以不先声明类型?你觉得 a、b、c 的值分别是多少?能说明理由么?
    TIPS:如果你对这块机制不了解,建议试着反编译一下字节码文件。 6.1 测试源码
    1. public class Test {
    2.    
    3.     int e = 6;
    4.     Test() {
    5.         int c = 1;
    6.         this.f = 5;
    7.         int e = 66;
    8.     }
    9.     int f = 55;
    10.     int c = 11;
    11.     int b = 1;
    12.     {
    13.         a = 3;
    14.         b = 22;
    15.     }
    16.     int a = 33;
    17.     static {
    18.         d = 4;
    19.     }
    20.     static int d = 44;
    21.    
    22.     int g = 7;
    23.     int h = 8;
    24.     public int test(){
    25.         g = 77;
    26.         int h = 88;
    27.         System.out.println("h - 成员变量:" + this.h);
    28.         System.out.println("h - 局部变量: " + h);
    29.         return g;
    30.     }
    31.     public static void main(String[] args) {
    32.         System.out.println("a: " + new Test().a);
    33.         System.out.println("b: " + new Test().b);
    34.         System.out.println("c: " + new Test().c);
    35.         System.out.println("d: " + new Test().d);
    36.         System.out.println("f: " + new Test().f);
    37.         System.out.println("e: " + new Test().e);
    38.         System.out.println("g: " + new Test().test());
    39.     }
    40. }
    复制代码
    6.2 字节码反编译:
    1. // Decompiled by Jad v1.5.8g. Copyright 2001 Pavel Kouznetsov.
    2. // Jad home page: http://www.kpdus.com/jad.html
    3. // Decompiler options: packimports(3)
    4. // Source File Name:   Test.java
    5. import java.io.PrintStream;
    6. public class Test
    7. {
    8.     Test()
    9.     {
    10.         this.e = 6;
    11.         f = 55;
    12.         this.c = 11;
    13.         b = 1;
    14.         a = 3;
    15.         b = 22;
    16.         a = 33;
    17.         g = 7;
    18.         h = 8;
    19.         int c = 1;
    20.         f = 5;
    21.         int e = 66;
    22.     }
    23.     public int test()
    24.     {
    25.         g = 77;
    26.         int h = 88;
    27.         System.out.println((new StringBuilder("h - u6210u5458u53D8u91CFuFF1A")).append(this.h).toString());
    28.         System.out.println((new StringBuilder("h - u5C40u90E8u53D8u91CF: ")).append(h).toString());
    29.         return g;
    30.     }
    31.     public static void main(String args[])
    32.     {
    33.         System.out.println((new StringBuilder("a: ")).append((new Test()).a).toString());
    34.         System.out.println((new StringBuilder("b: ")).append((new Test()).b).toString());
    35.         System.out.println((new StringBuilder("c: ")).append((new Test()).c).toString());
    36.         new Test();
    37.         System.out.println((new StringBuilder("d: ")).append(d).toString());
    38.         System.out.println((new StringBuilder("f: ")).append((new Test()).f).toString());
    39.         System.out.println((new StringBuilder("e: ")).append((new Test()).e).toString());
    40.         System.out.println((new StringBuilder("g: ")).append((new Test()).test()).toString());
    41.     }
    42.     int e;
    43.     int f;
    44.     int c;
    45.     int b;
    46.     int a;
    47.     static int d = 4;
    48.     int g;
    49.     int h;
    50.     static
    51.     {
    52.         d = 44;
    53.     }
    54. }
    复制代码
    6.3 output:
      a: 33
      b: 22
      c: 11
      d: 44
      f: 5
      e: 6
      h - 成员变量:8
      h - 局部变量: 88
      g: 77




      
      
       
       

         
       

         
       
      
    复制代码
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|Java学习者论坛 ( 声明:本站资料整理自互联网,用于Java学习者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-5-20 20:00 , Processed in 0.494099 second(s), 50 queries .

    Powered by Discuz! X3.4

    © 2001-2017 Comsenz Inc.

    快速回复 返回顶部 返回列表