WWDC2014:留给微软的时间不多了!

声明:此文章摘自http://www.cnblogs.com/fczjuever/archive/2013/04/07/3005997.html

Java
Map遍历方式的选择

1. 阐述

  对于Java中Map的遍历方式,很多文章都推荐使用entrySet,认为其比keySet的效率高很多。理由是:entrySet方法一次拿到所有key和value的集合;而keySet拿到的只是key的集合,针对每个key,都要去Map中额外查找一次value,从而降低了总体效率。那么实际情况如何呢?

  为了解遍历性能的真实差距,包括在遍历key+value、遍历key、遍历value等不同场景下的差异,我试着进行了一些对比测试。

2. 对比测试

  一开始只进行了简单的测试,但结果却表明keySet的性能更好,这一点让我很是费解,不都说entrySet明显好于keySet吗?为了进一步地进行验证,于是采用了不同的测试数据进行更详细的对比测试。

2.1 测试数据


2.1.1
HashMap测试数据


  • HashMap-1,大小为100万,key和value均为String,key的值为1、2、3……1000000:




Map<String, String> map = new
HashMap<String, String>();

String key,
value;

for (i = 1; i <= num;
i++) {

   
key = "" + i;

   
value = "value";

map.put(key, value);

}

  • HashMap-2,大小为100万,key和value均为String,key的值为50、100、150、200、……、50000000:




Map<String, String>
map = new HashMap<String, String>();

String key,
value;

for (i = 1; i <= num;
i++) {

   
key = "" + (i * 50);

   
value = "value";

map.put(key, value);

}

2.1.2 TreeMap测试数据

  • TreeMap-1,大小为100万,key和value均为String,key的值为1、2、3……1000000:




Map<String, String>
map = new TreeMap<String, String>();

String key,
value;

for (i = 1; i <= num;
i++) {

   
key = "" + i;

   
value = "value";

map.put(key, value);

}

  • TreeMap-2,大小为100万,key和value均为String,key的值为50、100、150、200、……、50000000,更离散:




Map<String, String>
map = new TreeMap<String, String>();

String key,
value;

for (i = 1; i <= num;
i++) {

   
key = "" + (i * 50);

   
value = "value";

map.put(key, value);

}

2.2 测试场景

  分别使用keySet、entrySet和values的多种写法测试三种场景:遍历key+value、遍历key、遍历value的场景。

2.2.1
遍历key+value


  • keySet遍历key+value(写法1):




Iterator<String> iter
= map.keySet().iterator();

while (iter.hasNext())
{

key =
iter.next();

value =
map.get(key);

}

  • keySet遍历key+value(写法2):




for (String key :
map.keySet()) {

value =
map.get(key);

}

  • entrySet遍历key+value(写法1):




Iterator<Entry<String, String>> iter
= map.entrySet().iterator();

Entry<String, String>
entry;

while (iter.hasNext())
{

entry =
iter.next();

key =
entry.getKey();

value =
entry.getValue();

}

  • entrySet遍历key+value(写法2):




for (Entry<String,
String> entry: map.entrySet()) {

key =
entry.getKey();

value =
entry.getValue();

}

2.2.2 遍历key


  • keySet遍历key(写法1):




Iterator<String> iter
= map.keySet().iterator();

while (iter.hasNext())
{

key =
iter.next();

}

  • keySet遍历key(写法2):




for (String key :
map.keySet()) {

}

  • entrySet遍历key(写法1):





Iterator<Entry<String, String>> iter
= map.entrySet().iterator();

while (iter.hasNext())
{

key =
iter.next().getKey();

}

  • entrySet遍历key(写法2):




for (Entry<String,
String> entry: map.entrySet()) {

key =
entry.getKey();

}

2.2.3 遍历value

  • keySet遍历value(写法1):




Iterator<String> iter
= map.keySet().iterator();

while (iter.hasNext())
{

value =
map.get(iter.next());

}

  • keySet遍历value(写法2):




for (String key :
map.keySet()) {

value =
map.get(key);

}

  • entrySet遍历value(写法1):




Iterator<Entry<String, String>> iter
= map.entrySet().iterator();

while (iter.hasNext())
{

value =
iter.next().getValue();

}

  • entrySet遍历value(写法2):




for (Entry<String,
String> entry: map.entrySet()) {

value =
entry.getValue();

}

  • values遍历value(写法1):




Iterator<String> iter
= map.values().iterator();

while (iter.hasNext())
{

value =
iter.next();

}

  • values遍历value(写法2):




for (String value :
map.values()) {

}

2.3 测试结果

2.3.1
HashMap测试结果
























单位:毫秒

HashMap-1

HashMap-2

keySet遍历key+value(写法1)

39

93

keySet遍历key+value(写法2)

38

87

entrySet遍历key+value(写法1)

43

86

entrySet遍历key+value(写法2)

43

85

























单位:毫秒

HashMap-1

HashMap-2

keySet遍历key(写法1)

27

65

keySet遍历key(写法2)

26

64

entrySet遍历key(写法1)

35

75

entrySet遍历key(写法2)

34

74

































单位:毫秒

HashMap-1

HashMap-2

keySet遍历value(写法1)

38

87

keySet遍历value(写法2)

37

87

entrySet遍历value(写法1)

34

61

entrySet遍历value(写法2)

32

62

values遍历value(写法1)

26

48

values遍历value(写法2)

26

48

2.3.2 TreeMap测试结果
























单位:毫秒

TreeMap-1

TreeMap-2

keySet遍历key+value(写法1)

430

451

keySet遍历key+value(写法2)

429

450

entrySet遍历key+value(写法1)

77

84

entrySet遍历key+value(写法2)

70

68

























单位:毫秒

TreeMap-1

TreeMap-2

keySet遍历key(写法1)

50

49

keySet遍历key(写法2)

49

48

entrySet遍历key(写法1)

66

64

entrySet遍历key(写法2)

65

63

































单位:毫秒

TreeMap-1

TreeMap-2

keySet遍历value(写法1)

432

448

keySet遍历value(写法2)

430

448

entrySet遍历value(写法1)

62

61

entrySet遍历value(写法2)

62

61

values遍历value(写法1)

46

46

values遍历value(写法2)

45

46

3. 结论

3.1 如果你使用HashMap


  1. 同时遍历key和value时,keySet与entrySet方法的性能差异取决于key的具体情况,如复杂度(复杂对象)、离散度、冲突率等。换言之,取决于HashMap查找value的开销。entrySet一次性取出所有key和value的操作是有性能开销的,当这个损失小于HashMap查找value的开销时,entrySet的性能优势就会体现出来。例如上述对比测试中,当key是最简单的数值字符串时,keySet可能反而会更高效,耗时比entrySet少10%。总体来说还是推荐使用entrySet。因为当key很简单时,其性能或许会略低于keySet,但却是可控的;而随着key的复杂化,entrySet的优势将会明显体现出来。当然,我们可以根据实际情况进行选择

  2. 只遍历key时,keySet方法更为合适,因为entrySet将无用的value也给取出来了,浪费了性能和空间。在上述测试结果中,keySet比entrySet方法耗时少23%。

  3. 只遍历value时,使用vlaues方法是最佳选择,entrySet会略好于keySet方法。

  4. 在不同的遍历写法中,推荐使用如下写法,其效率略高一些:




for (String key :
map.keySet()) {

value =
map.get(key);

}





for (Entry<String,
String> entry: map.entrySet()) {

key =
entry.getKey();

value =
entry.getValue();

}





for (String value :
map.values()) {

}

3.2 如果你使用TreeMap

  1. 同时遍历key和value时,与HashMap不同,entrySet的性能远远高于keySet。这是由TreeMap的查询效率决定的,也就是说,TreeMap查找value的开销较大,明显高于entrySet一次性取出所有key和value的开销。因此,遍历TreeMap时强烈推荐使用entrySet方法。

  2. 只遍历key时,keySet方法更为合适,因为entrySet将无用的value也给取出来了,浪费了性能和空间。在上述测试结果中,keySet比entrySet方法耗时少24%。

  3. 只遍历value时,使用vlaues方法是最佳选择,entrySet也明显优于keySet方法。

  4. 在不同的遍历写法中,推荐使用如下写法,其效率略高一些:




for (String key :
map.keySet()) {

value =
map.get(key);

}





for (Entry<String,
String> entry: map.entrySet()) {

key =
entry.getKey();

value =
entry.getValue();

}





for (String value :
map.values()) {

}

WWDC2014:留给微软的时间不多了!,布布扣,bubuko.com

时间: 2024-10-24 11:39:15

WWDC2014:留给微软的时间不多了!的相关文章

上周热点回顾(6.2-6.8)

热点随笔: · 为生活可以忍,侮辱技术行不行?(沈逸)· 程序员跳槽注意事项(麒麟子(Alex))· 中国的程序员们是否要声援微软小冰?(徐少侠)· 让 asp.net 在 mac 上飞(linli8)· 一次由注释引发的"血案"(Antineutrino)· WWDC2014:留给微软的时间不多了!(令狐葱同学)· 高大上!手把手教你在京东云擎上部署个人应用!(Chandler Qian)· 程序员的无奈(三):对不起,我不是重装电脑的(螃蟹(itxxz))· Swift学习笔记(一

微软不将帝国时代终极版上架Steam的原因?

毋庸置疑的是,<帝国时代>绝对是一款经典游戏.作为一款RTS名作,在过去的20年时间中<帝国时代>销量超过2000万部.数以千万计的玩家都沉溺于这款游戏中,<帝国时代>早已成为一款真正的史诗级战略游戏.在国内,<帝国时代>也有不少铁杆拥趸. 而作为微软手里的一张王牌,它将<帝国时代>看得很重.之所以不上架Steam,微软给出的解释听起来很勉强.在接受采访时微软制作人Jorg Neumann声称,<帝国时代:终极版>采用Xbox Liv

半年时间,能做的有很多!

我叫高凯乐,92年的,今天是来老男孩的第一天,新的开始,从头来过.机会留给有准备的人,因此,我觉得有必要写一篇决心书.制定一个学习大纲,时刻牢记自己来到这里的初衷!留给自己的时间并不多. 工作了为什么还回来学习,又为什么要学运维?有以下几个原因: 1.工作两年了,一直碌碌无为,感觉整天浑浑噩噩.混吃等死一样吧,从头到尾,毫无亮点. 2.看着父母苍老的面庞,满是茧子的手,却还在为了这个家.为了我而劳碌奔波,觉得自己很无力.无能 3.身边的朋友渐渐地都成家立业,自己依旧每天挤着公交,拿着3.4千的工

获取系统完成任务所需要的后台时间

有没有一种情况,当软件退出后,你还是需要运行一点东西,或者是需要很长时间来运行的一个代码.此时,就需要向后台申请时间了.但是官司方资料. 根据苹果文档中关于后台执行的描述,任何app都有10分钟左右的后台任务执行时间. 10分钟后,app会被iOS强行挂起. 但是,有5类app允许有“无限的”后台运行时间: 1.  Audio. 2.  Location/GPS. 3.  VoIP. 4.  Newsstand. 5.  Exernal Accessory . 你可以将任何app声明为上述5种类

利用好浏览器的空闲时间 --- requestIdleCallback

页面流畅与 FPS 页面是一帧一帧绘制出来的,当每秒绘制的帧数(FPS)达到 60 时,页面是流畅的,小于这个值时,用户会感觉到卡顿. 1s 60帧,所以每一帧分到的时间是 1000/60 ≈ 16 ms.所以我们书写代码时力求不让一帧的工作量超过 16ms. Frame 那么浏览器每一帧都需要完成哪些工作? 浏览器一帧内的工作 通过上图可看到,一帧内需要完成如下六个步骤的任务: 处理用户的交互 JS 解析执行 帧开始.窗口尺寸变更,页面滚去等的处理 rAF 布局 绘制 requestIdleC

雷军继续革命:小米品牌low质疑让工程师困惑

手机销量从第一落到第四,雷军承认小米需要补课,但他绝不反思,也不会向竞争对手学习,而是坚持小米方法论,在颠覆线上之后,再发起一场线下革命.长达两年的时间,这位著名的互联网思维“布道师”很少露面,除了一些不得不配合的活动,雷军几乎摒除了一切杂务,专注于小米业务. 专访安排在小米MIX发布后的第二天晚上.雷军的办公室在五彩城小米总部的15层,面积不大,二十平左右,跟豪华更是沾不上边,除了他的办公桌,就是一张长桌,周围摆放六把椅子. 封面 | 雷军继续革命 李亚婷 中国企业家杂志 雷军看上去有些疲惫,

人工智能、大数据、金融和SaaS四大风口上看风向

(上图为IDG资本创始合伙人熊晓鸽)? 前言:企业服务创业的最后一道壁垒 4月,IDG资本创始合伙人熊晓鸽在一个CEO的晚宴上遇到了GE的CEO.GE是一家市值数千亿美元的公司,业务涉及飞机发动机.发电设备.金融服务.软件开发等庞大的企业级产品与服务.在这个晚宴上,GE CEO问熊晓鸽,为什么中国没有出现为企业提供服务的大型公司? 熊晓鸽认为这可能有两点原因.一是这可能与国有企业投资重点有关,中国的国有企业是IT的最大用户,但并没有真正投入大量资金用于IT和软件开发.另一方面是中国的风险投资不太

除了价格 三星还得这样做

实事求是地讲,三星如今称得上是"屋漏偏逢连夜雨".在刚发布的2014年第三季度营收.运营利润大幅下滑的同时,还得面对微软的诉讼以及内部人事的变动,显得颇为无奈.而导致出现如此尴尬局面的原因就在于,三星移动通信部门的疲态,智能移动终端销量骤然陷入增长停滞乃至下滑的状态. 三星也承认要想扭转不利局面,颇为困难.但不管如何,前面有HTC的前车之鉴,三星开始早早地做出准备,以回应业绩的低迷和外界的不利消息.其中,智能移动终端降价只是"复兴计划"中的一小部分,三星要做的还有许

面对最菜TI战队,OpenAI在Dota2上输的毫无还手之力

作者:Tony Peng 去年,OpenAI 的 1v1 AI 击败了世界顶尖选手 Dendi,OpenAI CTO Greg Brockman 承诺:明年,我们会带着 5v5 的 AI bot 重回 TI.今天,他们履行了诺言,带着全新的 OpenAI Five,意欲挑战全世界最顶尖的 Dota 2 人类玩家.然而,51 分钟的比赛之后,OpenAI 经历了一场完败. 据介绍,本届 TI8 的很多参赛队伍都报名想参加与 AI 的比赛,OpenAI 今天遇到了第一个对手:来自巴西的战队 paiN