JAVA三种遍历机制的性能比较

Java List集合最大值最小值查找:从遍历到Stream API的三种方案详解 在Java集合操作中,查找最大值和最小值是基础且高频的需求,其核心原理基于元素间的比较。Java通过Comparable和Comparator接口定义了对象间的排序规则,这是实现比较的基石。从技术价值看,高效的极值查找能提升数据处理性能,尤其在处理大数据集时影响显著。常见的应用场景包括数据分析、排行榜单生成、资源调度中的最优选择等。本文聚焦于Java List集合,深入探讨手动遍历、Collections工具类和Stream API这三种主流方案,并结合Comparator构建与空安全处理等热词,分析其实现 阅读详情

现阶段我所知道JAVA遍历机制有三种

  • for循环
  • forEach循环
  • Iterator循环

JAVA三种遍历机制的性能比较

 

JAVA数据结构千千万,但是大部分都是对基础数据结构的封装,比较HashMap依赖于Node数组,LinkedList底层是链表,ArrayList对数组的再封装......扯远了

总结来说,JAVA的基础数据结构,我觉得有两种

  • 数组
  • 链表

如果是加上Hash(Hash的操作与数组以及链表不太一致),就是三种

因为平常开发大部分都优先选择包装后的数据结构,所以下面我会使用

  • ArrayList(包装后的数组)
  • LinkedList(包装后的链表)
  • HashSet(包装后的Hash类型数组)

这三种数据结构在遍历机制不同的时候时间的差异

可能有人对我为什么不对比HashMap呢,因为JAVA设计中,是先实现了Map,再实现Set。如果你有阅读过源码就会发现:每个Set子类的实现中,都有一个序列化后的Map对应属性实现,而因为Hash的查找时间复杂度为O(1),得出key后查找value的时间大致是一致的,所以我不对比HashMap。

题外话

我在阅读《疯狂JAVA》读到:JAVA的设计者将Map的内部entry数组中的value设为null进而实现了Set。因为我是以源码以及官方文档为准,具体我不清楚正确与否,但是因为Hash中的key互不相同,Set中元素也互不相同,所以我认为这个观点是正确的。

为了测试的公平性,我会采取以下的限定

  • 每种数据结构的大小都设置三种量级
  • 10
  • 100
  • 1000
  • 元素都采用随机数生成
  • 遍历进行操作都为输出当前元素的值

注:时间开销受本地环境的影响,可能测量值会出现变化,但是总体上比例是正确的

ArrayList的比较

  • 代码

public class TextArray {

private static Random random;

private static List<Integer> list1;

private static List<Integer> list2;

private static List<Integer> list3;

public static void execute(){

random=new Random();

initArray();

testForWith10Object();

testForEachWith10Object();

testIteratorWith10Object();

testForWith100Object();

testForEachWith100Object();

testIteratorWith100Object();

testForWith1000Object();

testForEachWith1000Object();

testIteratorWith1000Object();

}

private static void testForWith10Object(){

printFor(list1);

}

private static void testForWith100Object(){

printFor(list2);

}

private static void testForWith1000Object(){

printFor(list3);

}

private static void testForEachWith10Object(){

printForeach(list1);

}

private static void testForEachWith100Object(){

printForeach(list2);

}

private static void testForEachWith1000Object(){

printForeach(list3);

}

private static void testIteratorWith10Object() {

printIterator(list1);

}

private static void testIteratorWith100Object() {

printIterator(list2);

}

private static void testIteratorWith1000Object() {

printIterator(list3);

}

private static void printFor(List<Integer> list){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

for(int i=0,length=list.size();i<length;i++){

System.out.print(list.get(i)+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("for for "+list.size()+":"+(end-start)+"ms");

}

private static void printForeach(List<Integer> list){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

for(int temp:list){

System.out.print(temp+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("foreach for "+list.size()+":"+(end-start)+"ms");

}

private static void printIterator(List<Integer> list){

System.out.println();

System.out.print("data:");

Iterator<Integer> it=list.iterator();

long start=System.currentTimeMillis();

while(it.hasNext()){

System.out.print(it.next()+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("iterator for "+list.size()+":"+(end-start)+"ms");

}

private static void initArray(){

list1=new ArrayList<>();

list2=new ArrayList<>();

list3=new ArrayList<>();

for(int i=0;i<10;i++){

list1.add(random.nextInt());

}

for(int i=0;i<100;i++){

list2.add(random.nextInt());

}

for(int i=0;i<1000;i++){

list3.add(random.nextInt());

}

}

}

  • 输出(忽略对元素的输出)
for for 10:1ms
foreach for 10:0ms
iterator for 10:2ms
for for 100:5ms
foreach for 100:4ms
iterator for 100:12ms
for for 1000:33ms
foreach for 1000:7ms
iterator for 1000:16ms
复制代码
  • 10 100 1000 for 1ms 5ms forEach 0ms 4ms Iterator 2ms 12ms
  • 结论
  • for的性能最不稳定,foreach次之,Iterator最好
  • 使用建议
  1. 在数据量不明确的情况下(可能1w,10w或其他),建议使用Iterator进行遍历
  2. 在数据量明确且量级小的时候,优先使用foreach
  3. 需要使用索引时,使用递增变量的开销比for的要小

LinkedList的比较

  • 代码

public class TextLinkedList {

private static Random random;

private static List<Integer> list1;

private static List<Integer> list2;

private static List<Integer> list3;

public static void execute(){

random=new Random();

initList();

testForWith10Object();

testForEachWith10Object();

testIteratorWith10Object();

testForWith100Object();

testForEachWith100Object();

testIteratorWith100Object();

testForWith1000Object();

testForEachWith1000Object();

testIteratorWith1000Object();

}

private static void testForWith10Object() {

printFor(list1);

}

private static void testForEachWith10Object() {

printForeach(list1);

}

private static void testIteratorWith10Object() {

printIterator(list1);

}

private static void testForWith100Object() {

printFor(list2);

}

private static void testForEachWith100Object() {

printForeach(list2);

}

private static void testIteratorWith100Object() {

printIterator(list2);

}

private static void testForWith1000Object() {

printFor(list3);

}

private static void testForEachWith1000Object() {

printForeach(list3);

}

private static void testIteratorWith1000Object() {

printIterator(list3);

}

private static void printFor(List<Integer> list){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

for(int i=0,size=list.size();i<size;i++){

System.out.print(list.get(i));

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("for for "+list.size()+":"+(end-start)+"ms");

}

private static void printForeach(List<Integer> list){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

for(int temp:list){

System.out.print(temp+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("foreach for "+list.size()+":"+(end-start)+"ms");

}

private static void printIterator(List<Integer> list){

System.out.println();

System.out.print("data:");

Iterator<Integer> it=list.iterator();

long start=System.currentTimeMillis();

while(it.hasNext()){

System.out.print(it.next()+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("iterator for "+list.size()+":"+(end-start)+"ms");

}

private static void initList() {

list1=new LinkedList<>();

list2=new LinkedList<>();

list3=new LinkedList<>();

for(int i=0;i<10;i++){

list1.add(random.nextInt());

}

for(int i=0;i<100;i++){

list2.add(random.nextInt());

}

for(int i=0;i<1000;i++){

list3.add(random.nextInt());

}

}

}

  • 输出(忽略对元素的输出)
for for 10:0ms
foreach for 10:1ms
iterator for 10:0ms
for for 100:1ms
foreach for 100:0ms
iterator for 100:3ms
for for 1000:23ms
foreach for 1000:25ms
iterator for 1000:4ms
  • 10 100 1000 for 0ms 1ms forEach 1ms 0ms Iterator 0ms 3ms
  • 结论
  • foreach的性能最不稳定,for次之,Iterator最好
  • 使用建议
  1. 尽量使用Iterator进行遍历
  2. 需要使用索引时,使用递增变量的开销比for的要小

HashSet的比较

注:因Hash遍历算法与其他类型不一致,所以取消了for循环的比较

  • 代码

public class TextHash {

private static Random random;

private static Set<Integer> set1;

private static Set<Integer> set2;

private static Set<Integer> set3;

public static void execute(){

random=new Random();

initHash();

testIteratorWith10Object();

testForEachWith10Object();

testIteratorWith100Object();

testForEachWith100Object();

testIteratorWith1000Object();

testForEachWith1000Object();

}

private static void testIteratorWith10Object() {

printIterator(set1);

}

private static void testForEachWith10Object() {

printForeach(set1);

}

private static void testIteratorWith100Object() {

printIterator(set2);

}

private static void testForEachWith100Object() {

printForeach(set2);

}

private static void testIteratorWith1000Object() {

printIterator(set3);

}

private static void testForEachWith1000Object() {

printForeach(set3);

}

private static void initHash() {

set1=new HashSet<>();

set2=new HashSet<>();

set3=new HashSet<>();

for(int i=0;i<10;i++){

set1.add(random.nextInt());

}

for(int i=0;i<100;i++){

set2.add(random.nextInt());

}

for(int i=0;i<1000;i++){

set3.add(random.nextInt());

}

}

private static void printIterator(Set<Integer> data){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

Iterator<Integer> it=data.iterator();

while (it.hasNext()){

System.out.print(it.next()+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("iterator for "+data.size()+":"+(end-start)+"ms");

}

private static void printForeach(Set<Integer> data){

System.out.println();

System.out.print("data:");

long start=System.currentTimeMillis();

for(int temp:data){

System.out.print(temp+" ");

}

System.out.println();

long end=System.currentTimeMillis();

System.out.println("foreach for "+data.size()+":"+(end-start)+"ms");

}

}

  • 输出(忽略对元素的输出)
iterator for 10:0ms
foreach for 10:0ms
iterator for 100:6ms
foreach for 100:0ms
iterator for 1000:30ms
foreach for 1000:9ms
  • 10 100 1000 foreach 0ms 0ms Iterator 0ms 6ms
  • 结论
  • foreach性能遥遥领先于Iterator
  • 使用建议
  • 以后就选foreach了,性能好,写起来也方便。

总结

  1. for循环性能在三者的对比中总体落于下风,而且开销递增幅度较大。以后即使在需要使用索引时我宁愿使用递增变量也不会使用for了。
  2. Iterator的性能在数组以及链表的表现都是最好的,应该是JAVA的设计者优化过了。在响应时间敏感的情况下(例如web响应),优先考虑。
  3. foreach的性能属于两者之间,写法简单,时间不敏感的情况下我会尽量选用。

以上就是我对常见数据结构遍历机制的一点比较,虽然只是很初步,但是从中我也学到了很多东西,希望你们也有所收获。

Java面试要点63 - Java Map的遍历方式性能对比 通过对Java Map遍历方式的深入分析和性能测试,我们可以清楚地认识到不同遍历方式的特点和适用场景。entrySet方式通过直接访问键值对条目,在大多数场景下都能提供最优的性能表现。而keySet虽然实现简单,但在大数据量场景下可能因为额外的值查找操作而带来性能损耗。forEach方法则在代码简洁性和执行效率之间取得了很好的平衡,特别适合简单的遍历场景。Iterator的价值主要体现在需要在遍历过程中安全删除元素的场景。在实际开发中,应该根据具体的业务需求、数据规模和并发情况,选择最适合的遍历方式。 阅读详情

相关推荐

Java从根上理解 ConcurrentHashMap:缓存机制与性能优化

是 Java 并发编程中一款高性能、线程安全的哈希表。通过理解其核心原理、缓存机制以及性能优化策略,可以更好地在实际项目中应用,提高系统的并发性能和响应速度。在使用时,可以根据实际需求选择合适的缓存更新策略,以确保缓存数据的准确性和及时性。

C_V_Better的博客 1263

JAVA遍历机制的性能的比较

本文首发于cartoon的博客 转载请注明出处:cartoonyu.github.io/cartoon-blo… 缘由 近段时间在写leetcode的Lemonade Change时候,发现了for循环与forEach循环的耗时是不一致的,在提交记录上面差了一倍...... 平常开发绝大部分业务逻辑的实现都需要遍历机制的帮忙,虽说也有注意到各数据结构操作的性能比较,...

weixin_33943347的博客 328

爬取百度图片

最开始,我们想要爬取图片,首先需要打开百度图库,然后在搜索栏中输入自己想要的图片(比如说壁纸)。接着右键检查,点击网络:起初可能没有名称信息,刷新界面就可以了。打开信息,查看标头内容可以看到请求URL为:复制这串URL,然后在浏览器中打开这个就是我们搜索的壁纸图片的网页内容。怎么找到图片的URL呢?在上述内容中,找到data,可以发现里面每隔一个aiEditData,下面代码的形式是一样的,就相当于一张图片。

weixin_54143563的博客 1943

java几种集合遍历速度对比

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34081595的博客 3146

Ubuntu环境下rknn-toolkit2的安装与兼容性解析

本文详细解析了在Ubuntu系统上安装瑞芯微rknn-toolkit2工具链的完整流程与关键注意事项。文章重点剖析了rknn-toolkit2与旧版rknn-toolkit的核心兼容性问题,强调两者在API、模型格式及运行时库上互不兼容,并推荐使用Conda虚拟环境进行隔离管理,为RK3566、RK3588等开发板的AI模型部署提供清晰的实践指南。

weixin_29041767的博客 375

【KITTI数据集中Raw_Data数据标定文件中的参数关系解读】

上一节本人将KITTI Odometry数据集中的参数文件进行了解释。本节主要针对一些做融合slam的人,将Raw_Data数据标定文件中的参数按照自己的理解做如下阐述。其中,所讲之处如有错误,欢迎各位批评指正。

weixin_43389152的博客 1527

Java高级编程:集合

文章目录集合与数组存储数据概述:数组存储的特点:数组存储的弊端:集合存储的优点:Collection接口单列集合框架结构Collection接口常用方法: 集合与数组存储数据概述: 集合、数组都是对多个数据进行存储操作的结构,简称Java容器。 说明:此时的存储,主要指的是内存层面的存储,不涉及到持久化的存储(.txt,.jpg,.avi,数据库中) 数组存储的特点: 一旦初始化以后,其长度就确定了。 数组一旦定义好,其元素的类型也就确定了。我们也就只能操作指定类型的数据了。 比如:String[]

soulmate______的博客 1199

避开这些坑!晶圆封装中Wire Bonding(引线键合)的5种常见不良与实战调试心得

本文深入探讨晶圆封装中Wire Bonding(引线键合)的5种常见不良现象,包括Wire Offset、BSOB不良、球径/球厚异常、弧度不良和IMC问题。通过实际案例和参数优化方案,帮助工程师提升封装质量和可靠性,特别适用于半导体封装领域的专业人士。

weixin_33672109的博客 527

key的原理(vue)

面试题:vue中的key有什么作用?(key的内部原理) 1. 虚拟DOM中key的作用: key是虚拟DOM对象的标识,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】, 随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的差异比较,比较规则如下: 2.对比规则: (1).旧虚拟DOM中找到了与新虚拟DOM相同的key: ①.若虚拟DOM中内容没变, 直接使用之前的真实DOM! ②.若虚拟DOM中内容变了, 则生成新的真实DOM,随后替换掉页面中之前的真实DOM。 (2).旧虚拟DOM中未找到

qq_52135740的博客 769

Synares病毒实战:如何从U盘感染中恢复你的Excel和EXE文件(附专杀工具推荐)

本文详细介绍了Synares感染型病毒的典型特征与传播机制,特别是其通过U盘感染Excel和EXE文件的行为。文章提供了一套从应急隔离、诊断到使用专杀工具进行深度清除与文件恢复的完整实战流程,并推荐了有效的安全软件和修复方法,旨在帮助用户最大程度救回重要数据并构建长效安全防护习惯。

weixin_29230649的博客 1829

猫群优化算法(CSO)详解:从生物灵感到智能优化

猫群优化算法(CSO)是一种模拟猫科动物行为的群体智能优化算法。该算法基于猫的两种主要行为模式:搜寻状态(全局探索)和跟踪状态(局部开发)。CSO通过混合率(MR)动态调整两种模式的比例,实现探索与开发的平衡。算法核心包括搜寻模式的变异操作和跟踪模式的速度-位移模型,具有收敛性能好、全局搜索能力强等特点。相比传统优化算法,CSO在高维复杂问题中表现优异,已成功应用于函数优化、图像处理等多个领域。算法性能受混合率、变化域等参数影响,自适应参数策略可进一步提升优化效果。

qq_42212808的博客 620

Java数组深度解析:内存、遍历、复制与常用工具类实战

在Java开发中,数组是最基础也最容易被误解的数据结构之一。它既像C语言中的原生类型,本质上却是引用对象,存储在堆内存中,且类型由JVM动态生成。理解数组的声明、创建和初始化方式,是掌握其内存模型和引用传递原理的第一步。数组的遍历看似简单,但传统for、增强for以及Stream方式各有适用场景;复制数组时,System.arraycopy和Arrays.copyOf能大幅提升效率,避免手动循环。排序、二分查找、内容比较等操作则可直接依赖Arrays工具类完成,其中asList转换、多维数组浅拷贝等细节常成

weixin_34101914的博客 258

小梅哥Xilinx FPGA学习笔记11——亚稳态

亚稳态就是D触发器输入信号在其数据窗口期内发生变化,导致D触发器的输出进入一段时间的不稳定状态,有可能发生振荡,并最终随机稳定在高电平或者低电平。

m0_51430584的博客 631

java数组遍历效率_JAVA遍历机制的性能的比较

缘由近段时间在写leetcode的Lemonade Change时候,发现了for循环与forEach循环的耗时是不一致的,在提交记录上面差了一倍......平常开发绝大部分业务逻辑的实现都需要遍历机制的帮忙,虽说也有注意到各数据结构操作的性能比较,但是忽视了遍历机制性能的差异。原本前两天就开始动手写,拖延症......正文现阶段我所知道JAVA遍历机制有三种for循环forEach循环Itera...

weixin_35377028的博客 805

Ardupilot chibios IO固件,IO与FMU通信,固件下载(3)

目录 文章目录目录摘要 摘要 本节主要记录自己学习IO与FMU通信

陌城烟雨 2801

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

java 遍历两两比较数_JAVA遍历机制的性能的比较

缘由近段时间在写leetcode的Lemonade Change时候,发现了for循环与forEach循环的耗时是不一致的,在提交记录上面差了一倍......平常开发绝大部分业务逻辑的实现都需要遍历机制的帮忙,虽说也有注意到各数据结构操作的性能比较,但是忽视了遍历机制性能的差异。原本前两天就开始动手写,拖延症......正文现阶段我所知道JAVA遍历机制有三种for循环forEach循环Itera...

weixin_39643679的博客 531

visio安装包

Microsoft Office Visio 是一款专业的制图软件。利用经过更新的形状、协作工具和数据链接图表,创建专业级图表以简化复杂的信息。

java 循环对比_java遍历机制性能的比较详解

缘由近段时间在写leetcode的Lemonade Change时候,发现了for循环与forEach循环的耗时是不一致的,在提交记录上面差了一倍......平常开发绝大部分业务逻辑的实现都需要遍历机制的帮忙,虽说也有注意到各数据结构操作的性能比较,但是忽视了遍历机制性能的差异。原本前两天就开始动手写,拖延症......正文现阶段我所知道JAVA遍历机制有三种for循环forEach循环Itera...

weixin_42374930的博客 398

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

java iterator 遍历顺序_for 、foreach 、iterator 三种遍历方式的比较

习惯用法for、foreach循环、iterator迭代器都是我们常用的一种遍历方式,你可以用它来遍历任何东西:包括数组、集合等for 惯用法:List list = new ArrayList();String[] arr = new String[]{"1,2,3,4"};for(int i = 0;i < arr.length;i++){System.out.println(arr[i...

weixin_42227109的博客 1129

for 、foreach 、iterator 三种遍历方式的比较

习惯用法 for、foreach循环、iterator迭代器都是我们常用的一种遍历方式,你可以用它来遍历任何东西:包括数组、集合等 for 惯用法: List<String> list = new ArrayList<String>(); String[] arr = new String[]{"1,2,3,4"}; for(int i = 0;i < ar...

weixin_30596023的博客 150

Java常用的7中遍历方式速度比较

&amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;这段时间接触到一个后台返回列表排序的问题,列表返回给前端速度很慢,采用Java8中并行流的方式很快,串行很慢,想测试一下Java8中不同数据量7种遍历方式速度的比较。 &amp;gt; &amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;之

热爱技术、喜欢学习、乐于分享 2089

HashMap概述及其三种遍历方式(简单明了)

一、HashMap概述; HashMap是一个散列表,它存储的是键值对(key-value)映射; HashMap继承AbstractMap,实现了Map,Cloneable,Serializable接口; HashMap的实现不是同步的,线程不安全,但是效率高; HashMap允许null键和null值,是基于哈希表的Map接口实现; 哈希表的作用是用来保证键的唯一性; HashMap的实例有两个参数影响其性能:初试容量和加载因子,当哈希表中的条目数超出加载因子与当前容量的乘积时,要对哈希表进行reha

qq_43273025的博客 2053

Java里多个Map的性能比较

原文地址:http://blog.hongtium.com/java-map-skiplist/ Java里多个Map的性能比较(TreeMap、HashMap、ConcurrentSkipListMap) Category: Theroy, 学习笔记 Tags: map, SkipList 7 Comments 问题: 比较Java原生的 3种Ma

some_do的专栏 1061
上一篇: redis内、外部数据结构大揭秘
下一篇: 一次 JVM FullGC 的排查过程及解决方案!
加班不秃顶
博客等级 码龄7年 1822粉丝 599原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值