各种动态渲染Element方式的性能探究

【引自雕刻零碎的博客】一、性能优化的原则及方法论

树立原则:动态渲染进入一个Dom元素,首先需要保证动态渲染操作必须尽可能少对原有dom树的影响,影响重绘及重排。

确定方法论:必须寻找一个容器来缓存渲染期间生成的dom结构(操作必须尽可能少对原有dom树的影响),然后再进行一次渲染到目标element中。

二、生成期间DOM缓存的选择

  • DocumentFragment(文档碎片对象,选择原因:脱离于文档流)
  • 临时Element(选择原因:新element脱离于文档流)
    • createElement,再一步步进行渲染
    • 通过描述Dom的String(下称:DomString),转化为Dom对象
      • 临时Element+innerHTML+cloneNode返回最外层element元素对象,再进行插入appendChild,必要时还需要选择器方法讲某一个Element对象提取出来
      • XML字符串通过解析生成Element对象(注意,不是HTMLxxxElement对象,是Element对象),然后将该对象appendChild进去
  • 临时字符串(选择原因:借助innerHTML渲染,一次渲染)

三、DocumentFragment的优缺点

基本模式:


  1. var fragment = document.createDocumentFragment(); 
  2.     fragment.appendChild( 
  3.         ...    //生成Element的IIFE 
  4.     )  

  1. //IIFE示例,根据配置创建元素 
  2. var ConfigVar = { 
  3.   ELname:"div", 
  4.   id:"blablabla", 
  5.   name:"balblabla", 
  6.   class:"ClassName" 
  7. (function(Config){ 
  8.       var el = document.createElement(Config.ELname); 
  9.           el.className = (Config.class || ""); 
  10.     for (let AttrName in Config){ 
  11.           if (AttrName == "class")continue; 
  12.           el.setAttribute(AttrName,Config[AttrName]); 
  13.     } 
  14.       return el; 
  15. })(ConfigVar)  

优点

1、脱离于文档流,操作不会对Dom树产生影响

2、在每一次生成临时Element时候就可以将该Element对象的引用保存下来,而不需要多次用选择器再次获取。

缺点

兼容性只是达到IE9+

http://caniuse.com/#search=DocumentFragment

四、createElement的优缺点

基本模式


  1. var el = document.createElement("ElementName");     
  2.     el.className = ""; 
  3.     el.setAttribute("AttrName",AttrValue); 
  4.     el.setAttribute("AttrName",AttrValue); 
  5.     ... 
  6.     el.appendChild(         
  7.           ... //生成Element的IIFE,见上文 
  8.     );  

优点

1、新创建的元素脱离于文档流,操作不会对Dom树产生影响

2、兼容性最好

3、在每一次生成临时Element时候就可以将该Element对象的引用保存下来,而不需要多次用选择器再次获取。

缺点

每一次调用setAttribute方法都是一次次对Element进行修改,此处具有潜在的性能损耗。

五、DomString——临时Element+innerHTML+cloneNode的优缺点

基本模式


  1. var domString2Dom = (function(){ 
  2.     if (window.HTMLTemplateElement){ 
  3.         var container = document.createElement("template"); 
  4.         return function(domString){ 
  5.             container.innerHTML = domString; 
  6.             return container.content.firstChild.cloneNode(true) 
  7.         } 
  8.     }else{ 
  9.         //对不支持的template 的浏览器还有兼容性方法没写,所以不支持tr,td等些元素inner进div中。 
  10.         var container = document.createElement("div"); 
  11.         return function(domString){ 
  12.             container.innerHTML = domString; 
  13.             return container.firstChild.cloneNode(true) 
  14.         }         
  15.     } 
  16. })();  

  1. var template = domString2Dom('<div class="TestClass" Arg="TestArg"></div>'); 
  2. for (var index = 0; index < 80; index++) {     
  3.   template.appendChild( 
  4.     (function(){ 
  5.       var el = domString2Dom("<div>M</div>"); 
  6.       return el 
  7.     })() 
  8.   )                 
  9. }  

优点

创建Dom之后不需要多次进行setAttribute

缺点

1、临时元素不能包裹一些特定的元素(不能在所有浏览器的所有 HTML 元素上设置 innerHTML 属性)

2、解析的过程进行了很多其余的操作。此处具有潜在的性能损耗。

3、插入的字符串第一层Node只允许有一个元素

六、DomString——XML解析的优缺点

基本模式


  1. var XMLParser = function () { 
  2.     var $DOMParser = new DOMParser(); 
  3.     return function (domString) { 
  4.         if (domString[0] == "<") { 
  5.             var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml"); 
  6.             return doc.firstChild; 
  7.         } 
  8.         else { 
  9.             return document.createTextNode(domString); 
  10.         } 
  11.     }; 
  12. }();  

  1. var template = XMLParser('<div class="TestClass" Arg="TestArg"></div>'); 
  2. for (var index = 0; index < 80; index++) { 
  3.   template.appendChild((function () { 
  4.     var el = XMLParser("<div>M</div>"); 
  5.     return el; 
  6.   })()); 
  7. }  

优点

DomString方法中通用性最强的,虽然IE10+才支持DOMParser,但是IE9以下的有替代方法

缺点

1、解析的过程本身就具有潜在的性能损耗。

2、只能得到刚刚创建最外层元素的克隆。子元素的引用还需要用选择器。

3、插入的字符串第一层Node只允许有一个元素

七、临时字符串的优缺点

基本模式:


  1. var template = document.createElement("div"); 
  2. template.innerHTML = `<div class="TestClass" Arg="TestArg"> 
  3.                         Test TextNode 
  4.                         ${(function(){ 
  5.                           var temp = new Array(8); 
  6.                           for (var index = 0; index < 80; index++) { 
  7.                             temp[index]="<div>M</div>" 
  8.                           } 
  9.                           return temp.join() 
  10.                         }())} 
  11.                       </div>` //需要增加的一大段Element  

优点

1、通用性最强,不需要逐步创建一大堆无用的Element对象引用

2、运用es6模板字符串编码优雅,不需要字符串用加号进行链接

缺点

1、如果是直接给出配置Config进行渲染需要进行字符串的生成

2、只能得到刚刚创建最外层元素的引用。子元素的引用还需要用选择器。

八、Template元素

由于HTML5中新增了template元素

其特点就是有一个content属性是HTMLDocumentFragment对象,所以可以包容任何元素

基本范式是:


  1. var template = document.createElement("template"); 
  2. template.innerHTML = `<div class="TestClass" Arg="TestArg"> 
  3.                         Test TextNode 
  4.                         ${(function(){ 
  5.                           var temp = new Array(8); 
  6.                           for (var index = 0; index < 80; index++) { 
  7.                             temp[index]="<div>M</div>" 
  8.                           } 
  9.                           return temp.join() 
  10.                         }())} 
  11.                       </div>` //需要增加的一大段Element 
  12. // template.content 是HTMLDocumentFragment  

优点

比div要好很多,作为临时元素容器的包容性更强

缺点

兼容性不好:http://caniuse.com/#search=HTML%20templates 在不支持的浏览器中表示为HTMLUnknownElement

九、各种方法的效率对比

测试代码:(由于笔者不太熟悉各种浏览器性能的BUG,这里的代码如果有不足请指正),代码由typescript进行编写,也可以用babel进行编译。


  1. /** 
  2.  * @param Count:渲染DOM结构的次数 
  3.  */ 
  4. var DateCount = { 
  5.     TimeList : {}, 
  6.     time:function(Str){ 
  7.         console.time(Str); 
  8.     }, 
  9.     timeEnd:function(Str){ 
  10.         console.timeEnd(Str); 
  11.     } 
  12. }; 
  13. //==================工具函数====================== 
  14. var domString2Dom = (function () { 
  15.     var container; 
  16.     if (window.HTMLTemplateElement) { 
  17.         container = document.createElement("template"); 
  18.         return function (domString) { 
  19.             container.innerHTML = domString; 
  20.             return container.content.firstChild.cloneNode(true); 
  21.         }; 
  22.     } 
  23.     else { 
  24.         //对不支持的template 的浏览器还有兼容性方法没写,所以不支持tr,td等些元素inner进div中。 
  25.         container = document.createElement("div"); 
  26.         return function (domString) { 
  27.             container.innerHTML = domString; 
  28.             return container.firstChild.cloneNode(true); 
  29.         }; 
  30.     } 
  31. })(); 
  32. var XMLParser = (function () { 
  33.     var $DOMParser; 
  34.     if (window.DOMParser) { 
  35.         $DOMParser = new DOMParser(); 
  36.         return function (domString) { 
  37.             if (domString[0] == "<") { 
  38.                 var doc = $DOMParser.parseFromString(domString, "application/xhtml+xml"); 
  39.                 return doc.firstChild; 
  40.             } 
  41.             else { 
  42.                 return document.createTextNode(domString); 
  43.             } 
  44.         }; 
  45.     }else{ 
  46.         $DOMParser = new ActiveXObject("Microsoft.XMLDOM"); 
  47.         return function (domString) { 
  48.             if (domString[0] == "<") { 
  49.                 $DOMParser.async = false; 
  50.                 $DOMParser.loadXML(domString);    
  51.                 return $DOMParser 
  52.             } 
  53.             else { 
  54.                 return document.createTextNode(domString); 
  55.             }                 
  56.         } 
  57.  
  58.     } 
  59.  
  60. })(); 
  61. //=============================================== 
  62.  
  63. var Test = function(Count){ 
  64.     //保留这种写法,能够在移动端平台中不依靠控制台进行效率测试 
  65.     // var DateCount = { 
  66.     //     TimeList : {}, 
  67.     //     time:function(Str){ 
  68.     //         this.TimeList[Str] = Date.now(); 
  69.     //     }, 
  70.     //     timeEnd:function(Str){ 
  71.     //         alert(Str+(Date.now() - this.TimeList[Str])); 
  72.     //     } 
  73.     // } 
  74.  
  75.         //基准测试1: 
  76.     DateCount.time("无临时div + 不需要字符串拼接 + innerHTML:") 
  77.     for (let index = 0; index < Count; index++) { 
  78.         (function(){ 
  79.             var template = document.createElement("div"); 
  80.                 template.className = "TestClass"; 
  81.                 template.setAttribute("Arg","TestArg") 
  82.                 template.innerHTML = ` Test TextNode 
  83. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  84. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  85. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  86. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  87. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  88. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  89. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  90. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  91. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  92. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  93. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  94. <div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div><div child="true">M</div> 
  95. ` //需要增加的一大段Element,共100个子级div 
  96.             return template 
  97.         }())   
  98.     } 
  99.     DateCount.timeEnd("无临时div + 不需要字符串拼接 + innerHTML:") 
  100.  
  101.     //基准测试2: 
  102.     DateCount.time("createElement+appendChild写法:") 
  103.     for (let index = 0; index < Count; index++) { 
  104.         (function(){ 
  105.             var template = document.createElement("div"); 
  106.                 template.className = "TestClass"; 
  107.                 template.setAttribute("Arg","TestArg") 
  108.  
  109.                 template.appendChild(document.createTextNode('Test TextNode')); 
  110.                 for (let index = 0; index < 100; index++) { 
  111.                     let element = document.createElement("div"); 
  112.                         element.setAttribute("child","true"); 
  113.                         element.appendChild(document.createTextNode("M")) 
  114.                         template.appendChild(element) 
  115.                 } 
  116.             return template 
  117.         }())   
  118.     } 
  119.     DateCount.timeEnd("createElement+appendChild写法:")     
  120.  
  121.     //DocumentFragment  
  122.     DateCount.time("DocumentFragment+ createElement+appendChild 写法:") 
  123.     for (let index = 0; index < Count; index++) { 
  124.         (function(){ 
  125.             var fragment = document.createDocumentFragment(); 
  126.                 fragment.appendChild(function(){ 
  127.                     var template = document.createElement("div"); 
  128.                         template.className = "TestClass"; 
  129.                         template.setAttribute("Arg","TestArg") 
  130.  
  131.                         template.appendChild(document.createTextNode('Test TextNode')); 
  132.                         for (let index = 0; index < 100; index++) { 
  133.                             let element = document.createElement("div"); 
  134.                                 element.setAttribute("child","true"); 
  135.                                 template.appendChild(element) 
  136.                         } 
  137.                     return template; 
  138.                 }()); 
  139.  
  140.             return fragment 
  141.         }())   
  142.     } 
  143.     DateCount.timeEnd("DocumentFragment+ createElement+appendChild 写法:")     
  144.  
  145.     //DomString——临时Element+innerHTML+cloneNode 
  146.     // DateCount.time("DomString——临时Element+innerHTML+cloneNode:") 
  147.     // for (let index = 0; index < Count; index++) { 
  148.     //     (function(){ 
  149.     //         var template = domString2Dom('<div class="TestClass" Arg="TestArg"></div>'); 
  150.     //         for (let index = 0; index < 100; index++) {     
  151.     //             template.appendChild( 
  152.     //                 (function(){ 
  153.     //                     var el = domString2Dom("<div child='true'>M</div>"); 
  154.     //                     return el 
  155.     //                 })() 
  156.     //             )                 
  157.     //         } 
  158.     //         return template; 
  159.     //     }())   
  160.     // } 
  161.     // DateCount.timeEnd("DomString——临时Element+innerHTML+cloneNode:")     
  162.  
  163.     //DomString——XML解析 
  164.     // DateCount.time("DomString——XML解析:") 
  165.     // for (let index = 0; index < Count; index++) { 
  166.     //     (function(){ 
  167.     //         var template = XMLParser('<div class="TestClass" Arg="TestArg"></div>'); 
  168.     //         for (let index = 0; index < 100; index++) { 
  169.     //             template.appendChild((function () { 
  170.     //                 var el = XMLParser("<div child='true'>M</div>"); 
  171.     //                 return el; 
  172.     //             })()); 
  173.     //         } 
  174.     //     }())   
  175.     // } 
  176.     // DateCount.timeEnd("DomString——XML解析:")    
  177.  
  178.     //临时div + 临时字符串拼接: 
  179.     DateCount.time("临时div + 字符串拼接:") 
  180.     for (let index = 0; index < Count; index++) { 
  181.         (function(){ 
  182.             let template = document.createElement("div"); 
  183.             template.innerHTML = `<div class="TestClass" Arg="TestArg"> 
  184.                                     Test TextNode 
  185.                                     ${(function(){ 
  186.                                         let temp = ""; 
  187.                                         for (let index = 0; index < 100; index++) { 
  188.                                             temp+="<div child='true'>M</div>" 
  189.                                         } 
  190.                                         return temp 
  191.                                     }())} 
  192.                                 </div>` //需要增加的一大段Element 
  193.             return template.firstChild; 
  194.          }())   
  195.     } 
  196.     DateCount.timeEnd("临时div + 字符串拼接:") 
  197.  
  198.     //临时template + 临时字符串拼接: 
  199.     DateCount.time("临时template + 字符串拼接:") 
  200.     for (let index = 0; index < Count; index++) { 
  201.         (function(){ 
  202.             var template = document.createElement("template"); 
  203.             template.innerHTML = `<div class="TestClass" Arg="TestArg"> 
  204.                                     Test TextNode 
  205.                                     ${(function(){ 
  206.                                         let temp = ""; 
  207.                                         for (let index = 0; index < 100; index++) { 
  208.                                             temp+="<div child='true'>M</div>" 
  209.                                         } 
  210.                                         return temp 
  211.                                     }())} 
  212.                                 </div>` //需要增加的一大段Element 
  213.             return template.content; 
  214.          }())   
  215.     } 
  216.     DateCount.timeEnd("临时template + 字符串拼接:") 
  217.  
  218.     //临时template + createElement+appendChild 写法 
  219.     DateCount.time("template + createElement+appendChild 写法:") 
  220.     for (let index = 0; index < Count; index++) { 
  221.         (function(){ 
  222.             var template = document.createElement("template"); 
  223.                 template.appendChild(function(){ 
  224.                     var template = document.createElement("div"); 
  225.                         template.className = "TestClass"; 
  226.                         template.setAttribute("Arg","TestArg") 
  227.  
  228.                         template.appendChild(document.createTextNode('Test TextNode')); 
  229.                         for (let index = 0; index < 100; index++) { 
  230.                             let element = document.createElement("div"); 
  231.                                 element.setAttribute("child","true"); 
  232.                                 template.appendChild(element) 
  233.                         } 
  234.                     return template; 
  235.                 }()); 
  236.             return template.content 
  237.          }())   
  238.     } 
  239.     DateCount.timeEnd("template + createElement+appendChild 写法:") 
  240.  
  241. }; 
  242.  
  243. for (var key of [1,10,100,1000]) { 
  244.     console.log("Start"+key); 
  245.     Test(key); 

十、结论

经过笔者基本依据手上平台进行测试,

  • 无临时div + 不需要字符串拼接 + innerHTML // createElement+appendChild写法:性能低,无论在桌面端还是移动端,在IE/Edge系还是 Webkit系都是同样的表现
  • domString 方法:性能最差
  • DocumentFragment+ createElement+appendChild 写法:性能在桌面WebKit端表现最好,移动端也有不错的表现
  • 字符串拼接:临时div + 字符串拼接/临时template +
    字符串拼接:性能表现基本一致,桌面端WebKit上:比DocumentFragment(或tmplate) +
    createElement+appendChild性能差多了;与之相反,在IE系inneHTML的性能最高,是前者的x十倍。在移动端上两者性能相近,innerHTML略差一点点。
  • template + createElement+appendChild 写法:与DocumentFragment+ createElement+appendChild 写法效率相仿。

具体数据测试之后再补充。

(待续)

作者:雕刻零碎

来源:51CTO

时间: 2024-11-18 04:13:24

各种动态渲染Element方式的性能探究的相关文章

各种动态渲染Element方式 的性能探究

一.性能优化的原则及方法论 树立原则:动态渲染进入一个Dom元素,首先需要保证动态渲染操作必须尽可能少对原有dom树的影响,影响重绘及重排. 确定方法论:必须寻找一个容器来缓存渲染期间生成的dom结构(操作必须尽可能少对原有dom树的影响),然后再进行一次渲染到目标element中. 二.生成期间DOM缓存的选择 DocumentFragment(文档碎片对象,选择原因:脱离于文档流) 临时Element(选择原因:新element脱离于文档流) createElement,再一步步进行渲染 通

每日一博 | 各种动态渲染 Element 方式的性能探究

树立原则:动态渲染进入一个Dom元素,首先需要保证动态渲染操作必须尽可能少对原有dom树的影响,影响重绘及重排.确定方法论:必须寻找一个容器来缓存渲染期间生成的dom结构(操作必须尽可能少对原有dom树的影响),然后再进行一次渲染到目标element中. 本文来自开源中国社区 [http://www.oschina.net]

iOS中播放gif动态图的方式探讨

iOS中播放gif动态图的方式探讨 一.引言     在iOS开发中,UIImageView类专门来负责图片数据的渲染,并且UIImageView也有帧动画的方法来播放一组图片,但是对于gif类型的数据,UIImageView中并没有现成的接口提供给开发者使用,在iOS中一般可以通过两种方式来播放gif动态图,一种方式是通过ImageIO框架中的方法将gif文件中的数据进行解析,再使用coreAnimation核心动画来播放gif动画,另一种方式计较简单,可以直接通过webView来渲染gif图

SQL Server执行动态SQL正确方式

SQL Server执行动态SQL的话,应该如何实现呢?下面就为您介绍SQL Server执行动态SQL两种正确方式,希望可以让您对SQL Server执行动态SQL有更深的了解. 动态SQL:code that is executed dynamically.它一般是根据用户输入或外部条件动态组合的SQL语句块.动态SQL能灵活的发挥SQL强大的功能.方便的解决一些其它方法难以解决的问题.相信使用过动态SQL的人都能体会到它带来的便利,然而动态SQL有时候在执行性能(效率)上面不如静态SQL,

ArrayList和LinkedList的几种循环遍历方式及性能对比分析

主要介绍ArrayList和LinkedList这两种list的五种循环遍历方式,各种方式的性能测试对比,根据ArrayList和LinkedList的源码实现分析性能结果,总结结论. 通过本文你可以了解(1)List的五种遍历方式及各自性能 (2)foreach及Iterator的实现 (3)加深对ArrayList和LinkedList实现的了解. 阅读本文前希望你已经了解ArrayList顺序存储和LinkedList链式的结构,本文不对此进行介绍. 相关:HashMap循环遍历方式及其性

JavaScript 启动性能探究

本文讲的是JavaScript 启动性能探究, 作为 web 开发者,都知道 web 项目开发到最后,页面规模很容易变的很大. 但 加载 一个网页远不止从网线上传送字节码那么简单.浏览器下载了页面脚本之后,它还必须解析.解释和运行它们.这篇文章将深入 JavaScript 的这一部分,研究 为什么这一过程会拖慢应用程序的启动,以及 如何 解决. 过去,人们并没有花很多时间优化 JavaScript 的解析.编译步骤.我们总是期望解析器在遇到 script 标签时立即解析和执行代码,但是情况并非如

iOS给图片添加滤镜&amp;使用openGLES动态渲染图片详解及实例_IOS

iOS给图片添加滤镜&使用openGLES动态渲染图片 给图片增加滤镜有这两种方式: CoreImage / openGLES  下面先说明如何使用CoreImage给图片添加滤镜, 主要为以下步骤: #1.导入CIImage格式的原始图片 #2.创建CIFilter滤镜 #3.用CIContext将滤镜中的图片渲染出来 #4.导出渲染后的图片 参考代码: //导入CIImage CIImage *ciImage = [[CIImage alloc] initWithImage:[UIImage

ListView实现下拉动态渲染数据

这是一篇关于LIstView实现动态数据渲染的文章! 首先我们讲讲数据是如何来规划的 一般情况下我们有两种规划方案 前提比如我们数据是100条+ 第一:一次性把100条数据fetch过来 然后由前端JS代码来做分页处理(如每次渲染10条) 第二:在server端做处理通过?page=n的方式 每次需要第几页数据就fetch第几页的数据 利弊 第一种方案的优点是 一次性把数据全部载入完成 如果数据量很大的情况下可能会有很长的loading时间 但是对于服务端的压力就会减少请求次数 第二种方案的优点

HashMap循环遍历方式及其性能对比

主要介绍HashMap的四种循环遍历方式,各种方式的性能测试对比,根据HashMap的源码实现分析性能结果,总结结论. 1. Map的四种遍历方式 下面只是简单介绍各种遍历示例(以HashMap为例),各自优劣会在本文后面进行分析给出结论. (1) for each map.entrySet() Java 1 2 3 4 5 Map<String, String> map = new HashMap<String, String>(); for (Entry<String,