对于Java循环中的For和For-each,哪个更快

Which is Faster For Loop or For-each in Java

对于Java循环中的For和For-each,哪个更快

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

对于Java循环中的For和For-each,哪个更快

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

for-each实现方法

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

public class TestForeach {
    List 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 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);

这是测试结果:

对于Java循环中的For和For-each,哪个更快

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

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

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

对于Java循环中的For和For-each,哪个更快

原因分析

一些初学者可能想知道为什么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不需要关心集合的具体实现。如果需要替换集合,无需修改代码即可轻松替换。

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

Original: https://www.cnblogs.com/kohler21/p/16592740.html
Author: 愚生浅末
Title: 对于Java循环中的For和For-each,哪个更快

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/599425/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 《SpringBoot官网文档:2.1.5》

    404. 抱歉,您访问的资源不存在。 可能是网址有误,或者对应的内容被删除,或者处于私有状态。 代码改变世界,联系邮箱 contact@cnblogs.com 园子的商业化努力-困…

    数据库 2023年6月14日
    075
  • 开源二三事|ShardingSphere 与 Database Mesh 之间不得不说的那些事

    背景 前段时间,以 Apache ShardingSphere 核心团队组建的创业公司 SphereEx,正式对外推出了 Database Mesh 2.0 概念以及与之相配套的开…

    数据库 2023年6月16日
    0105
  • 为什么 SQL 语句使用了索引,但却还是慢查询?

    一、索引与慢查询 聊一聊索引和慢查询,经常遇到的一个问题:一个SQL语句使用了索引,为什么还是会记录到慢查询日志之中?为了说明,创建一个表t,该表3个字段,一个主键索引,一个普通索…

    数据库 2023年5月24日
    098
  • 力扣leetcode刷题记录1—-

    【以下题目来源均来自力扣leetcode】 World 表: 【描述】name 是这张表的主键。这张表的每一行提供:国家名称、所属大陆、面积、人口和 GDP 值。 【问题】如果一个…

    数据库 2023年6月16日
    075
  • etcd和Zookeeper孰优孰劣对比

    背景 最近在看到Pachyderm的介绍时,看到作者拿YARN和Kubernetes做类比,拿Zookeeper和etcd做对比。YARN和Kubernetes的类比还相对比较好理…

    数据库 2023年6月11日
    082
  • MySQL 的日志:binlog

    前言:binlog 用于记录数据库执行 写入性操作的日志信息,以二进制的形式保留在磁盘中。它是由 Server 层进行记录的,使用任何存储引擎都会产生 binlog。 实验准备 我…

    数据库 2023年5月24日
    082
  • RocksDB线程局部缓存

    在开发过程中,我们经常会遇到并发问题,解决并发问题通常的方法是加锁保护,比如常用的spinlock,mutex或者rwlock,当然也可以采用无锁编程,对实现要求就比较高了。对于任…

    数据库 2023年6月9日
    073
  • Spring Bean的作用域

    Spring Bean的作用域或者说范围主要有五种: 作用 描述 singleton 在spring IoC容器仅存在一个Bean实例,Bean以单例方式存在,bean作用域范围的…

    数据库 2023年6月16日
    056
  • MySQL函数学习(四)—–聚合函数

    注:笔记旨在记录 四、MySQL 聚合函数 \ 函 数 名 称 作 用 完 成 1 MAX 求最大值 勾 2 MIN 求最小值 勾 3 COUNT 求数量 勾 4 BIT_COUN…

    数据库 2023年6月16日
    069
  • MySQL–用通配符进行过滤(LIKE操作符)

    1、LIKE操作符 怎样搜索产品名中包含文本anvil的所有产品?用简单的比较操作符肯定不行,必须使用通配符。利用通配符可创建比较特定数据的搜索模式。在这个例子中,如果你想找出名称…

    数据库 2023年6月16日
    069
  • 一个小工具帮你搞定实时监控Nginx服务器

    Linux运维工程师的首要职责就是保证业务7 x 24小时稳定的运行,监控Web服务器对于查看网站上发生的情况至关重要。关注最多的便是日志变动,查看实时日志文件变动大家第一反应应该…

    数据库 2023年6月9日
    0139
  • 一个线程的打工故事

    前言 前几天小强去阿里巴巴面试Java岗,止步于二面。 他和我诉苦自己被虐的多惨多惨,特别是深挖线程和线程池的时候,居然被问到不知道如何作答。 对于他的遭遇,结合他过了一面的那个嘚…

    数据库 2023年6月16日
    0120
  • SpringBoot下使用AOP做日志

    AOP实现接口执行时间的计算: SpringBoot项目导入spring-boot-starter-aop依赖 编写切面类 类上加@Aspect注解,表明这是一个切面类 类上加@C…

    数据库 2023年6月14日
    0114
  • 连接数据库空异常

    解决过程(嫌麻烦可以直接看结论): 首先我以为是我的数据库驱动名字什么的没有写对,但是确实是对的,使用的是 com.mysql.cj.jdbc.Driver ,也没有发现多余的空格…

    数据库 2023年6月16日
    072
  • docker部署redis集群

    docker部署redis集群 1.0 安装环境 1.1 安装Centos7 Docker官方建议在Ubuntu中安装,因为Docker是基于Ubuntu发布的,而且一般Docke…

    数据库 2023年6月9日
    072
  • super 和 this 的区别

    一、二者的区别 1.属性的区别:this访问本类中的属性,如果本类没有此属性则从父类中继续查找。super访问父类中的属性。2.方法的区别:this访问本类中的方法,如果本类没有此…

    数据库 2023年6月11日
    068
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球