Which is Faster For Loop or For-each in Java

对于Java中的Loop或Foreach,哪个更快

通过本文,您可以了解一些集合遍历技巧。

Java遍历集合有两种方法。一个是最基本的for循环,另一个是jdk5引入的for each。通过这种方法,我们可以更方便地遍历数组和集合。但是你有没有想过这两种方法?哪一个遍历集合更有效?

for-each实现方法

For-each不是一种新语法,而是Java的语法糖(语法糖百度百科)。在编译时,编译器将此代码转换为迭代器实现,并将其编译为字节码。我们可以通过执行命令javap-verbose-Testforeach反编译以下编译代码:

public class TestForeach {
List<Integer> integers;
public void testForeach(){
for(Integer i : integers){ }
}
}

获得的详细字节码如下:

public void testForeach();
descriptor: ()V
flags: ACC_PUBLIC
Code:
stack=1, locals=3, args_size=1
0: aload_0
1: getfield #2 // Field integers:Ljava/util/List;
4: invokeinterface #3, 1 // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
9: astore_1
10: aload_1
11: invokeinterface #4, 1 // InterfaceMethod java/util/Iterator.hasNext:()Z
16: ifeq 32
19: aload_1
20: invokeinterface #5, 1 // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
25: checkcast #6 // class java/lang/Integer
28: astore_2
29: goto 10
32: return
LineNumberTable:
line 11: 0
line 13: 29
line 14: 32
LocalVariableTable:
Start Length Slot Name Signature
29 0 2 i Ljava/lang/Integer;
0 33 0 this Ltest/TestForeach;
}

此字节码的一般含义是使用getfileld命令来获取integers变量并且调用List.iterator来获取迭代器实例和调用iterator.hasNext。如果返回true,调用iterator.next方法。

请看,这是迭代器遍历集合的实现逻辑。

基准测试

现在让我们使用for循环方法和for-each方法进行测试。

public class ForLoopTest {

    public static void main(String[] args) {
List<Integer> arrayList = new ArrayList<>();
for (int i = 0; i < 10000000; i++) {
arrayList.add(i);
} long arrayListStartTime = System.currentTimeMillis();
for (int i = 0; i < arrayList.size(); i++) {
arrayList.get(i);
} long arrayListCost =System.currentTimeMillis()-arrayListStartTime;
System.out.println("ArrayList for loop traversal cost: "+ arrayListCost); long arrayListForeachStartTime = System.currentTimeMillis();
for (Integer integer : arrayList) { } long arrayListForeachCost =System.currentTimeMillis()-arrayListForeachStartTime;
System.out.println("ArrayList foreach traversal cost: "+ arrayListForeachCost);

这是测试结果:

如你所见,结果是显而易见的。对于ArrayList,使用For循环方法的性能优于For each方法。

我们可以说for循环比for-each好吗?

答案是否定的。在下一个基准测试中,我们将ArrayList更改为LinkedList。

同样,这里是测试结果。

原因分析

一些初学者可能想知道为什么ArrayList使用for循环方法遍历得更快,而LinkedList则更慢,速度也非常慢?

这由ArrayList和LinkedList数据结构决定。

ArrayList底层使用数组存储元素。数组是连续的内存空间。数据可以通过索引获得。时间复杂度为O(1),因此速度很快。

LinkedList的底层是一个双向链表。使用for循环实现遍历,每次都需要从链表的头节点开始。时间复杂度为O(n*n)。

结论

  1. 使用ArrayList时,for循环方法更快,因为for-each由迭代器实现,并且需要执行并发修改验证。
  2. 使用LinkedList时,for-each比for循环快得多,因为LinkedList是通过使用双向链表实现的。每个寻址都需要从头节点开始。如果我们需要遍历LinkedList,我们需要避免使用for循环。
  3. 使用迭代器模式,for-each不需要关心集合的具体实现。如果需要替换集合,无需修改代码即可轻松替换。

欢迎关注公众号:愚生浅末。

对于Java中的Loop或For-each,哪个更快的更多相关文章

  1. Sql server 中count(1) 与 sum(1) 那个更快?

    上一篇中,简单的说明了下 count() 与 sum() 的区别,虽然count 函数是汇总行数的,不过我汇总行数的时候经常是使用SUM(1) ,那么问题来了,count(1) 与 sum(1)  那 ...

  2. Spring装配bean(在java中进行显式配置)

    1.简单介绍 Spring提供了三种装配机制: 1.在XML中进行显式配置: 2.在java中进行显式配置: 3.隐式的bean发现机制和自动装配. 其中,1和3项在项目中经常使用,而在java中进行 ...

  3. G1垃圾收集或者Java中垃圾收集的名词收集

    HotSpot WTF,热壶?我他奶奶的还热火呢,Heat,you know? 总之HotSpot是一种遵循java虚拟机规范的一种实现啦,当时并不是Sun公司搞出来的,而是另外一家公司,后来被Sun ...

  4. 如何在 Java 中正确使用 wait, notify 和 notifyAll(转)

    wait, notify 和 notifyAll,这些在多线程中被经常用到的保留关键字,在实际开发的时候很多时候却并没有被大家重视.本文对这些关键字的使用进行了描述. 在 Java 中可以用 wait ...

  5. java中常用的工具类(三)

    继续分享java中常用的一些工具类.前两篇的文章中有人评论使用Apache 的lang包和IO包,或者Google的Guava库.后续的我会加上的!谢谢支持IT江湖 一.连接数据库的综合类       ...

  6. Java中的wait和sleep

    sleep()和wait() 首先,Java中的多线程是一种抢占式的机制,而不是分时机制.抢占式的机制是有多个线程处于可运行状态,但是只有一个线程在运行. 这种机制决定了,对于同一对象的多线程访问,必 ...

  7. 深入分析 Java 中的中文编码问题

    登录 (或注册) 中文 IBM 技术主题 软件下载 社区 技术讲座 打印本页面 用电子邮件发送本页面 新浪微博 人人网 腾讯微博 搜狐微博 网易微博 Digg Facebook Twitter Del ...

  8. java中多线程中Runnable接口和Thread类介绍

    java中的线程时通过调用操作系统底层的线程来实现线程的功能的. 先看如下代码,并写出输出结果. // 请问输出结果是什么? public static void main(String[] args ...

  9. [转]深入分析 Java 中的中文编码问题

    收益匪浅,所以转发至此 原文链接: http://www.ibm.com/developerworks/cn/java/j-lo-chinesecoding/ 深入分析 Java 中的中文编码问题 编 ...

随机推荐

  1. 记一次 JDK SPI 配置不生效的问题 → 这么简单都不会,还是回家养猪吧

    开心一刻 今天去幼儿园接小侄女,路上聊起了天 小侄女:小叔,今天我吃东西被老师发现了 我:老师说了什么 小侄女:她说拿出来,跟小朋友一起分享 我:那你拿出来了吗 小侄女一脸可怜的看向我,说道:没有,我 ...

  2. 渗透测试之sql注入点查询

    一切教程在于安全防范,不在于攻击别人黑别人系统为目的 寻找sql注入点方法: 拿到网页后进行查找注入点: 1.通过单引号 ' ;    在 url 后面输入单引号进行回车(如果报错可能存在sql注入为 ...

  3. es6.4.2api

    这是讲数据库的数据导入到es里  所有用到了mysql! 1.依赖 <?xml version="1.0" encoding="UTF-8"?> & ...

  4. vue虚拟dom和diff算法

    vue的虚拟dom和diff算法 1.虚拟dom 虚拟dom,我的理解就是通过js对象的方式来具体化每一个节点,把dom树上面的每个节点都变为对象里的一个元素,元素的子元素变为子节点,节点上面的cla ...

  5. ”只用 1 分钟“ - 超简极速 Apk 签名 & 多渠道打包神器

    众所周知,渠道包作为当下国内 Android 应用市场常见的分发方式,当 APP 和后台交互或进行数据上报时,会带上各自的 channel 渠道信息,以此方便企业 & 开发者统计 APP 在各 ...

  6. Django——表单

    一.前言 看了下教程,以为表单很简单呢,结果搞了一两个钟才弄懂,哈哈哈,所以说不要小瞧每一件事. 先说明下HTTP请求: HTTP协议以"请求-回复"的方式工作.客户发送请求时,可 ...

  7. JS:!非

    取非运算符: 开关思想:0为false,1为true: 把一个变量中保存一个布尔值 然后在业务执行时,修改这个变量的值: 为取反 然后通过变量的值执行分支业务 例子: var a = "12 ...

  8. idea运行Tomcat出现 Address localhost:8080 is already in useAddress localhost:8080 is already in use

    使用IDEA运行 tomcat时出现 Address localhost:8080 is already in use,就很奇怪,我明明只有这一个程序呀,怎么还会被占用.后来想想可能就是被其他进程占用 ...

  9. Python: list列表的11个内置方法

    先来逼逼两句: 在实际开发中,经常需要将一组(不只一个)数据存储起来,以便后边的代码使用.在VBA中有使用数组,可以把多个数据存储到一起,通过数组下标可以访问数组中的每个元素.Python 中没有数组 ...

  10. CF484A Bits

    CF484A Bits 题目 https://codeforces.com/problemset/problem/484/A 题解 思路 知识点:贪心,位运算. 每位独立考虑,要使 \(1\) 的数量 ...