mysql new map_你可能没用过这种方式的集合!new HashMap<K,V>(){{put(K,V);}};

131b82420dfedd74da4477887dd6a0fa.png

一、HashMap的初始化

1、HashMap 初始化的文艺写法

HashMap 是一种常用的数据结构,一般用来做数据字典或者 Hash 查找的容器。普通青年一般会这么初始化:HashMap map =

new HashMap();map.put("Name", "June");map.put("QQ", "2572073701");

看完这段代码,很多人都会觉得这么写太啰嗦了,对此,文艺青年一般这么来了:HashMap map =

new HashMap() {

{

put("Name", "June");

put("QQ", "2572073701");

}

};

嗯,看起来优雅了不少,一步到位,一气呵成的赶脚。然后问题来了,有童鞋会问:纳尼?这里的双括号到底什么意思,什么用法呢?哈哈,其实很简单,看看下面的代码你就知道啥意思了。public class Test {

/*private static HashMap map = new HashMap() {     {      put("Name", "June");      put("QQ", "2572073701");     }    };*/

public Test() {

System.out.println("Constructor called:构造器被调用");

}

static {

System.out.println("Static block called:静态块被调用");

}

{

System.out.println("Instance initializer called:实例初始化块被调用");

}

public static void main(String[] args) {

new Test();

System.out.println("=======================");

new Test();

}}

输出: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_homeCDHJobsbinpvuv>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.javapackage 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_homeCDHJobsbinpvuv>

2、推而广之

这种写法,推而广之,在初始化 ArrayList、Set 的时候都可以这么玩,比如你还可以这么玩:List names = new ArrayList() {

{

for (int i = 0; i 

add("A" + i);

}

}};System.out.println(names.toString()); // [A0, A1, A2, A3, A4, A5, A6, A7, A8, A9]

3、文艺写法的潜在问题

文章开头提到的文艺写法的好处很明显就是一目了然。这里来罗列下此种方法的坏处,如果这个对象要串行化,可能会导致串行化失败。此种方式是匿名内部类的声明方式,所以引用中持有着外部类的引用。所以当串行化这个集合时外部类也会被不知不觉的串行化,当外部类没有实现serialize接口时,就会报错。

上例中,其实是声明了一个继承自HashMap的子类。然而有些串行化方法,例如要通过Gson串行化为json,或者要串行化为xml时,类库中提供的方式,是无法串行化Hashset或者HashMap的子类的,从而导致串行化失败。

解决办法,重新初始化为一个HashMap对象:new HashMap(map);

这样就可以正常初始化了。

4、执行效率问题

当一种新的工具或者写法出现时,猿们都会来一句:性能怎么样?(这和男生谈论妹纸第一句一般都是:“长得咋样?三围多少?”一个道理:))

关于这个两种写法我这边笔记本上测试文艺写法、普通写法分别创建 10,000,000 个 Map 的结果是 1217、1064,相差 13%。public class Test {

public static void main(String[] args) {

long st = System.currentTimeMillis();

/*      for (int i = 0; i  map = new HashMap() {        {         put("Name", "June");         put("QQ", "2572073701");        }       };      }      System.out.println(System.currentTimeMillis() - st); // 1217      */

for (int i = 0; i 

HashMap map = new HashMap();

map.put("Name", "June");

map.put("QQ", "2572073701");

}

System.out.println(System.currentTimeMillis() - st); // 1064

}}

5、由实例初始化块联想到的一些变量初始化问题

从代码上看,a 为什么可以不先声明类型?你觉得 a、b、c 的值分别是多少?能说明理由么?TIP:如果你对这块机制不了解,建议试着反编译一下字节码文件。

5.1 测试源码public class Test {

int e = 6;

Test() {

int c = 1;

this.f = 5;

int e = 66;

}

int f = 55;

int c = 11;

int b = 1;

{

a = 3;

b = 22;

}

int a =33;

static {

d = 4;

}

static int d = 44;

int g = 7;

int h = 8;

public int test() {

g = 77;

int h = 88;

System.out.println("h - 成员变量:" + this.h);

System.out.println("h - 局部变量: " + h);

return g;

}

public static void main(String[] args) {

System.out.println("a: " + new Test().a);

System.out.println("b: " + new Test().b);

System.out.println("c: " + new Test().c);

System.out.println("d: " + new Test().d);

System.out.println("f: " + new Test().f);

System.out.println("e: " + new Test().e);

System.out.println("g: " + new Test().test());

}}

5.2 字节码反编译:// 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.javaimport java.io.PrintStream;public class Test{

Test()

{

this.e = 6;

f = 55;

this.c = 11;

b = 1;

a = 3;

b = 22;

a = 33;

g = 7;

h = 8;

int c = 1;

f = 5;

int e = 66;

}

public int test()

{

g = 77;

int h = 88;

System.out.println((new StringBuilder("h - u6210u5458u53D8u91CFuFF1A")).append(this.h).toString());

System.out.println((new StringBuilder("h - u5C40u90E8u53D8u91CF: ")).append(h).toString());

return g;

}

public static void main(String args[])

{

System.out.println((new StringBuilder("a: ")).append((new Test()).a).toString());

System.out.println((new StringBuilder("b: ")).append((new Test()).b).toString());

System.out.println((new StringBuilder("c: ")).append((new Test()).c).toString());

new Test();

System.out.println((new StringBuilder("d: ")).append(d).toString());

System.out.println((new StringBuilder("f: ")).append((new Test()).f).toString());

System.out.println((new StringBuilder("e: ")).append((new Test()).e).toString());

System.out.println((new StringBuilder("g: ")).append((new Test()).test()).toString());

}

int e;

int f;

int c;

int b;

int a;

static int d = 4;

int g;

int h;

static

{

d = 44;

}}

5.3 输出结果:a: 33

b: 22

c: 11

d: 44

f: 5

e: 6

h - 成员变量:8

h - 局部变量: 88

g: 77

二、HashMap遍历方法示例

第一种:Map map = new HashMap();Iterator iter = map.entrySet().iterator();while (iter.hasNext()) {

Map.Entry entry = (Map.Entry) iter.next();

Object key = entry.getKey();

Object val = entry.getValue();}

效率高,以后一定要使用此种方式!

第二种:Map map = new HashMap();Iterator iter = map.keySet().iterator();while (iter.hasNext()) {

Object key = iter.next();

Object val = map.get(key);}

效率低,以后尽量少使用!

HashMap的遍历有两种常用的方法,那就是使用keyset及entryset来进行遍历,但两者的遍历速度是有差别的,下面请看实例:public class HashMapTest {

public static void main(String[] args) {

HashMap hashmap = new HashMap();

for (int i = 0; i 

hashmap.put("" + i, "thanks");

}

long bs = Calendar.getInstance().getTimeInMillis();

Iterator iterator = hashmap.keySet().iterator();

while (iterator.hasNext()) {

System.out.print(hashmap.get(iterator.next()));

}

System.out.println();

System.out.println(Calendar.getInstance().getTimeInMillis() - bs);

listHashMap();

}

public static void listHashMap() {

HashMap hashmap = new HashMap();

for (int i = 0; i 

hashmap.put("" + i, "thanks");

}

long bs = Calendar.getInstance().getTimeInMillis();

java.util.Iterator it = hashmap.entrySet().iterator();

while (it.hasNext()) {

java.util.Map.Entry entry = (java.util.Map.Entry) it.next();

// entry.getKey() 返回与此项对应的键

// entry.getValue() 返回与此项对应的值

System.out.print(entry.getValue());

}

System.out.println();

System.out.println(Calendar.getInstance().getTimeInMillis() - bs);

}}

对于keySet其实是遍历了2次,一次是转为iterator,一次就从hashmap中取出key所对于的value。而entryset只是遍历了第一次,他把key和value都放到了entry中,所以就快了。

注:Hashtable的遍历方法和以上的差不多!

ba5cd08314dcb4e0e79070adcc0b8d37.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值