for 、foreach 、iterator三种方式的比较
haoteby 2024-11-20 16:21 3 浏览
for、foreach循环、iterator迭代器都是我们常用的一种遍历方式,你可以用它来遍历任何东西:包括数组、集合等
for 惯用法:
List<String> list = new ArrayList<String>();
String[] arr = new String[]{"1,2,3,4"};
for(int i =0;i<arr.length;i++){
System.out.println(arr[i]);
}
for(int i =0;i<list.size();i++){
System.out.println(list.get(i));
}
foreach 惯用法:
String[] arr=new String[]{"1,2,3,4"};
List<String> list= new ArrayList<String>();
list.add("1");
list.add("2");
for(String str: arr){
System.out.println(str);
}
for(String item: list) {
System.out.println(item);
}
Iterator 惯用法:
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
}
速度对比
性能是我们选取某一种技术手段的一种考虑方式,且看这三种遍历方式的速度对比
List<Long> list = new ArrayList<Long>();
long maxLoop=2000000;
for(long i=0;i<maxLoop;i++){
list.add(i);
}
// for循环
long startTime = System.currentTimeMillis();
for(int i=0;i<list.size();i++){
;
}
long endTime=System.currentTimeMillis();
System.out.println(endTime-startTime+"ms");
// foreach 循环
startTime = System.currentTimeMillis();
for(Long lon: list){
;
}
endTime = System.currentTimeMillis();
System.out.println(endTime-startTime+"ms");
// iterator 循环
startTime = System.currentTimeMillis();
Iterator<Long> iterator = list.iterator();
while(iterator.hasNext()) {
iterator.next();
}
endTime=System.currentTimeMillis();
System.out.println(endTime-startTime+"ms");
4ms
16ms
9ms
由以上得知,for()循环是最快的遍历方式,随后是iterator()迭代器,最后是foreach循环
remove操作三种遍历方式的影响
for循环的remove
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for(int i=0;i<list.size();i++){
if("2".equals(list.get(i))){
System.out.println(list.get(i));
list.remove(list.get(i));
}
}
for循环可以直接进行remove,不会受到任何影响。
foreach 中的remove
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
for(String item: list) {
if("2".equals(item)) {
System.out.println(item);
list.remove(item);
}
}
你觉得这段代码的正确输出是什么?我们一起来探究一下
当我执行一下这段代码的时候,出现了以下的情况
由以上异常情况的堆栈信息得知,程序出现了并发修改的异常,为什么会这样?我们从错误开始入手,
at java.util.ArrayList$Itr.checkForComodification(ArrayList.java:909)
也就是这行代码,找到这行代码的所在地
final void checkForComodification() {
if(modCount != expectedModCount)
throw new ConcurrentModificationException();
}
你会好奇, modCount 和 expectedModCount 是什么变量?在我对 ArrayList 相关用法那篇文章中有比较详细的解释。我大致说明一下: modCount 相当于是程序所能够进行修改 ArrayList 结构化的一个变量,怎么理解?看几个代码片段
你能够从中获取什么共性的特征呢?没错,也就是涉及到其中关于ArrayList的 容量大小 和 __元素个数__的时候,就会触发modCount 的值的变化
expectedModCount这个变量又是怎么回事?从ArrayList 源码可知,这个变量是一个局部变量,也就是说每个方法内部都有expectedModCount 和 modCount 的判断机制,进一步来讲,这个变量就是 预期的修改次数,
先抛开这个不谈,我们先来谈论一下foreach(增强for循环)本身。
增强for循环是Java给我们提供的一个语法糖,如果将以上代码编译后的class文件进行反编译(使用jad工具)的话,可以得到以下代码:
Iterator iterator=item.iterator();
也就是说,其实foreach 每次循环都调用了一次iterator的next()方法
因此才会有这个堆栈信息:
at java.util.ArrayList$Itr.next(ArrayList.java:859)
下面我们来尝试分析一下这段代码报错的原因:
1、第一次 以 “1”的值进入循环,“1” != “2”, 执行下一次循环
2、第二次循环以"2"的值进入,判断相等,执行remove()方法(注意这个remove方法并不是 iterator的remove(),而是ArrayList的remove()方法),导致modCount++
3、再次调用next()的时候,modCount != expectedModCount ,所以抛出异常
Iterator迭代器的remove
使用迭代器进行遍历还有很多需要注意的地方:
正确的遍历
List<String> list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
it.remove();
}
这是一种正确的写法,如果输出语句和 remove()方法互换顺序怎么样呢?
错误的遍历 —— next() 和 remove() 执行顺序的问题
List<String>list = new ArrayList<String>();
list.add("1");
list.add("2");
list.add("3");
Iterator<String>it=list.iterator();
while(it.hasNext()){
it.remove();
System.out.println(it.next());
}
执行程序输出就会报错:
Exceptioninthread"main"java.lang.IllegalStateException
atjava.util.ArrayList$Itr.remove(ArrayList.java:872)
attest.SimpleTest.main(SimpleTest.java:46)
这又是为什么? 还是直接从错误入手:
定位到错误的位置
atjava.util.ArrayList$Itr.remove(ArrayList.java:872)
发现如果 lastRet 的值小于 0就会抛出非法状态的异常,这个lastRet是什么?
且看定义:
lastRet的赋值场景
由上面代码可以看出,当你执行next()方法的时候, lastRet 赋值为i,所以这个elementData[]中的下标最小是0,所以这个时候lastRet 最小的值是0, 那么只有当执行remove()方法的时候,lastRet的值赋值为-1,也就是说,你必须先执行一次next方法,再执行一次remove方法,才能够保证程序的正确运行。
错误的遍历 —— 使用Arrays.asList()
List<String> list = Arrays.asList("1","2","3");
Iterator<String> it = list.iterator();
while(it.hasNext()){
System.out.println(it.next());
it.remove();
}
这段代码执行之后的输出是怎样的呢?
1
Exceptioninthread"main"java.lang.UnsupportedOperationException
atjava.util.AbstractList.remove(AbstractList.java:161)
atjava.util.AbstractList$Itr.remove(AbstractList.java:374)
attest.SimpleTest.main(SimpleTest.java:50)
很不幸,这段代码也抛出了异常,直接从错误处入手发现,这个remove()方法调用的是AbstractList中的remove方法,跟进入发现有一段代码
remove()方法:
也就是说,只要这段代码执行了,都会报错,抛出异常
后记:
上述文章主要介绍了 for循环、foreach 循环、iterator 迭代器遍历元素的速度大小的比较
还介绍了各自遍历过程中 对remove操作的影响。
相关推荐
- Python爬虫进阶教程(二):线程、协程
-
简介线程线程也叫轻量级进程,它是一个基本的CPU执行单元,也是程序执行过程中的最小单元,由线程ID、程序计数器、寄存器集合和堆栈共同组成。线程的引入减小了程序并发执行时的开销,提高了操作系统的并发性能...
- A320-V2500发动机系统FADEC介绍(2)
-
目的全权数字发动机控制(FADEC)系统在所有飞行和运行阶段提供全范围发动机控制。...
- 三国志战棋版:玩家“二叔”用这套群DOT在比武中拿下31胜5负
-
声明:本文首发于今日头条,而后发布于“鼎叔闯三棋”的微信公众号、抖音、哔哩哔哩和小红书平台,如果在其他平台就是抄袭。...
- 真正的独一无二:Dot One 推出 DNA 定制系列 139英镑起
-
相信很多人在挑选衣物时有着这样的困扰,综合了性价比、面料等因素后好不容易找到了心仪的款式,还要担心是否会撞衫,不管是擦肩而过的陌生人还是身边的熟人,都令人尴尬。小部分人为此热衷于购买少量的古着或者限量...
- 崩铁:周年庆福利再升级,老角色加强时间确定,3.xdot体系反转
-
#埃安UT大一圈高级很多#...
- Dotgo推出RBMHub,扩大了CPaaS提供商的覆盖范围和功能
-
据telecompaper网7月15日报道,用于商业消息传递的RichCommunicationServices(RCS)解决方案的领先提供商Dotgo宣布推出RBMHub。RBMHub的推出扩大了C...
- 深度解析:快照取消Dot职业的将何去何从
-
写在前面曾几何时,术士的出现便被冠以dot大师的名头,从远古时期的献祭腐蚀虹吸不如暗牧一个痛,到TBC上满dot=荣誉击杀+1,到wlk接近全暴击的冰晶腐蚀,再到CTM就算了吧MOP的各种变态吸x放...
- 星穹铁道:抽卡芙卡之前,你必须了解什么是dot!
-
卡妈终于上线了,可还是有很多人不明白什么是dot伤害,抽了卡妈直接玩起了直伤流,把一个持续伤害的引爆器玩成了打手,卡妈打dot伤害是远高于直伤的,有了卡妈的玩家一直了解dot,不然这卡妈就真被玩成四不...
- 游戏界的闪耀星辰陨落:悼念知名游戏博主″dotα牛娃″
-
无尽哀思!在数字时代浪潮中,游戏不仅是消遣娱乐的代名词,更是连接心灵的桥梁,构筑了无数人的青春回忆。在这片浩瀚无垠的游戏宇宙中,有这样一位博主,他以独特的风采、深邃的洞察力和无尽的热情,成为了玩家心中...
- 直击2017新加坡同性恋聚会Pink Dot,自由爱!
-
今年的“粉红点”又来啦~这个支持LGBT群体(男女同志、双性恋、跨性别等)群体的活动,从2009年起,已经在新加坡举办8年了!”这个非营利的同性恋权益活动,主要是希望大家了解到,不管一个人的性倾向或...
- python-dotenv,一款超级实用处理环境变量python库
-
python-dotenv,一款超级实用处理环境变量python库python-dotenv概述:...
- 亚马逊语音助手毫无征兆发笑 诡异至极吓坏用户
-
来源:新华网美国电商亚马逊7日承诺,将更改名下“亚历克萨”语音系统设置,令它不会莫名发笑,免得吓坏用户。“亚历克萨”是亚马逊开发的语音助手软件,可服从用户语音指令完成对话、播放音乐等任务。依照原来设计...
- 2022最火英文网名男女生
-
精选好听英文昵称带翻译1.moveon(离开)2.Monster(怪物)3.Solo吉他手4.Finish.(散场)...
- 智能家具 RecycleDot 的出现给传统家具厂商带来新的挑战
-
从可穿戴手环、手表到智能衣服,智能硬件逐步渗透到每一个领域。最近有一对父子MikeSandru和JohnSandru在自家的车库中设计了一款智能家具RecycleDot,给日渐萧条的家具行...
- 欧洲通信卫星公司 OneWeb 敦促印度DoT尽早批准提供卫星宽带服务
-
据telecomtalk2月17日报道,欧洲通信卫星公司EutelsatOneWeb近日敦促印度电信部(DoT)尽快批准其在印度部署双地球站网关的计划,以便连接其近地轨道(LEO)全球卫星星座,并...