首页 > 编程语言 >Java 中for循环和foreach循环哪个更快?

Java 中for循环和foreach循环哪个更快?

时间:2023-09-22 09:25:38浏览次数:36  
标签:mylist java List util 循环 foreach Java

摘要:本文由葡萄城技术团队于博客园发布。转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具、解决方案和服务,赋能开发者。

前言

在Java编程中,循环结构是程序员常用的控制流程,而for循环和foreach循环是其中比较常见的两种形式。关于它们哪一个更快的讨论一直存在。本文旨在探究Java中的for循环和foreach循环的性能差异,并帮助读者更好地选择适合自身需求的循环方式。通过详细比较它们的遍历效率、数据结构适用性和编译器优化等因素,我们将为大家揭示它们的差异和适用场景,以便您能够做出更明智的编程决策。

for循环与foreach循环的比较

小编认为for和foreach 之间唯一的实际区别是,对于可索引对象,我们无权访问索引。

for(int i = 0; i < mylist.length; i++) {
 if(i < 5) {
 //do something
 } else {
 //do other stuff
 }
}

但是,我们可以使用 foreach 创建一个单独的索引 int 变量。例如:

int index = -1;
for(int myint : mylist) {
 index++;
 if(index < 5) {
 //do something
 } else {
 //do other stuff
 }
}

现在写一个简单的类,其中有 foreachTest() 方法,该方法使用 forEach 迭代列表。

import java.util.List;

public class ForEachTest {
        List<Integer> intList;
        
    public void foreachTest(){
        for(Integer i : intList){

        }
    }
}

编译这个类时,编译器会在内部将这段代码转换为迭代器实现。小编通过执行 javap -verbose IterateListTest 反编译代码。

public void foreachTest();
    descriptor: ()V
    flags: ACC_PUBLIC
    Code:
      stack=1, locals=3, args_size=1
         0: aload_0
         1: getfield      #19                 // Field intList:Ljava/util/List;
         4: invokeinterface #21,  1           // InterfaceMethod java/util/List.iterator:()Ljava/util/Iterator;
         9: astore_2
        10: goto          23
        13: aload_2
        14: invokeinterface #27,  1           // InterfaceMethod java/util/Iterator.next:()Ljava/lang/Object;
        19: checkcast     #33                 // class java/lang/Integer
        22: astore_1
        23: aload_2
        24: invokeinterface #35,  1           // InterfaceMethod java/util/Iterator.hasNext:()Z
        29: ifne          13
        32: return
      LineNumberTable:
        line 9: 0
        line 12: 32
      LocalVariableTable:
        Start  Length  Slot  Name   Signature
            0      33     0  this   Lcom/greekykhs/springboot/ForEachTest;
      StackMapTable: number_of_entries = 2
        frame_type = 255 /* full_frame */
          offset_delta = 13
          locals = [ class com/greekykhs/springboot/ForEachTest, top, class java/util/Iterator ]
          stack = []
        frame_type = 9 /* same */

从上面的字节码我们可以看到:

a). getfield命令用于获取变量整数。

b).调用List.iterator获取迭代器实例

c).调用iterator.hasNext,如果返回true,则调用iterator.next方法。

下边来做一下性能测试。在 IterateListTest 的主要方法中,创建了一个列表并使用 for 和 forEach 循环对其进行迭代。

import java.util.ArrayList;
import java.util.List;

public class IterateListTest {
        public static void main(String[] args) {
                List<Integer> mylist = new ArrayList<>();
        for (int i = 0; i < 1000000; i++) {
            mylist.add(i);
        }

        long forLoopStartTime = System.currentTimeMillis();
        for (int i = 0; i < mylist.size(); i++) {mylist.get(i);}

        long forLoopTraversalCost =System.currentTimeMillis()-forLoopStartTime;
        System.out.println("for loop traversal cost for ArrayList= "+ forLoopTraversalCost);

        long forEachStartTime = System.currentTimeMillis();
        for (Integer integer : mylist) {}

        long forEachTraversalCost =System.currentTimeMillis()-forEachStartTime;
        System.out.println("foreach traversal cost for ArrayList= "+ forEachTraversalCost);
        }
}

结果如下:

总结

观察结果显示,for循环的性能优于for-each循环。然后再使用LinkedList比较它们的性能差异。对于 LinkedList 来说,for-each循环展现出更好的性能。ArrayList内部使用连续存储的数组,因此数据的检索时间复杂度为 O(1),通过索引可以直接访问数据。而 LinkedList 使用双向链表结构,当我们使用 for 循环进行遍历时,每次都需要从链表头节点开始,导致时间复杂度达到了 O(n*n),因此在这种情况下,for-each 循环更适合操作 LinkedList。

标签:mylist,java,List,util,循环,foreach,Java
From: https://www.cnblogs.com/powertoolsteam/p/17701802.html

相关文章

  • Odoo 通过Javascript调用模型中自定义方法
    实践环境Odoo14.0-20221212(CommunityEdition)代码实现在js脚本函数中调用模型中自定义方法:this._rpc({model:'demo.wizard',//模型名称,即模型类定义中_name的值method:'action_select_records_via_checkbox',//模型中自定义名称args:['arg_value......
  • Go 1.22 中的 For 循环
    原文在这里。由DavidChaseandRussCox发布于2023年9月19日Go1.21版本包含了对for循环作用域的预览更改,我们计划在Go1.22中发布此更改,以消除其中一种最常见的Go错误。问题如果你写过一定量的Go代码,你可能犯过一个错误,即在迭代结束后仍然保留对循环变量的引用......
  • odoo中用javascript调用model中定义好的方法,及要注意的坑
    odoo中如果前端界面要调用后台model中写好的方法,很简单。使用do_action即可,比如要调用改res.users的默认语言后执行的方法odoo.define('switch_language.SwitchLanguageMenu',function(require){"usestrict";varModel=require('web.Model');varsessi......
  • JAVA 后端 记录方法运行时间
     LocalDateTimeldStart=LocalDateTime.now();//记录开始时间//中间是需要计算时间的代码段落LocalDateTimeldEnd=LocalDateTime.now();//记录结束时间Durationdu=Duration.between(ldStart,ldEnd);LongcostSeconds=du.toMillis()/1000;System.out.println("postNurseCo......
  • java内存分配(堆,栈,方法区,常量池)图解
    大家都知道,java程序是运行在jvm(java虚拟机)上的,因此Java的内存分配是在JVM中进行的。那么在程序内存分配上面,大致分为:本地方法栈、程序计数器、虚拟机栈、java堆、方法区。这五类,本次主要讲解的是虚拟机栈、java堆和方法区中的内容。栈:存放基本数据类型的数据、引用数据类型的变量......
  • JAVA基础 —— 面向对象内存图
    JAVA基础——面向对象内存图......
  • java语言基础--对象内存图解
    在JVM内存里面主要分布有以下三个区域:栈:存放基础数据和自定义对象的引用堆:主要存储创建的对象,即new出来的对象。方法区:加载存放class文件(字节码文件)创建一个对象: 通过上图来看,程序是这样执行的:将StudentTest01.class文件加载到方法区将Student.class文件加载到方法区......
  • Java 序列化与反序列化的疑问
    关于序列化和反序列化的疑问为什么需要序列化和反序列化?因为计算机底层存储和传输都是二进制,所以需要将对象转化成字节数组。那么问题来了,只需要转成字节数组就行了,那为啥还要弄这么多东西?搞这么复杂?因为直接转生成的字节数组是不规则的,所以我们不能通过这样的字节数组把原......
  • 用javaweb技术设计一个网页需要什么软件
    对于使用JavaWeb技术设计一个网页,需要准备以下软件:JavaDevelopmentKit(JDK):这是Java开发的基本工具包,包括Java编译器、运行时环境和其他工具。IDE(集成开发环境):常见的JavaWeb开发IDE包括Eclipse、IntelliJIDEA和NetBeans。这些IDE提供了代码编辑、调试和部署等功能,使开发......
  • Java基础
    Java基础一个Java程序可以认为是一系列对象的集合,而这些对象通过调用彼此的方法来协同工作。基本语法大小写敏感:Java是大小写敏感的,这就意味着标识符Hello与hello是不同的。类名:对于所有的类来说,类名的首字母应该大写。如果类名由若干单词组成,那么每个单词的首字......