【问题标题】:Java loops. What is faster? [duplicate]Java 循环。什么更快? [复制]
【发布时间】:2021-07-27 12:02:28
【问题描述】:

哪个循环更快?

循环 1

for(String key : myList) {
    int index = myList.indexOf(key)
    System.out.println(index)
}

循环 2

int index;
for(String key : myList) {
    index = myList.indexOf(key)
    System.out.println(index)
}

感谢您的帮助。我正在尝试更多地了解性能。

【问题讨论】:

  • “哪个循环更快?” - 你为什么不跑马?编译器也有可能将其优化为完全相同的字节码......所以,你可能也想检查一下。
  • 您想通过这种级别的绩效衡量来实现什么目标?除非您拥有大量数据或已用尽其他优化,否则两者的性能都无关紧要。
  • 你在错误的地方寻找让你的代码更快的地方。不要在循环的每次迭代中执行myList.indexOf(key)。写int index = 0; for (String key : myList) { System.out.println(index); index++; }
  • @ErwinBolwidt 如果列表中有重复条目,则可能不会给出相同的结果。不清楚需要哪种行为。

标签: java performance loops


【解决方案1】:

你的问题很“有趣”,但是好的,这是你的答案:你需要检查字节码。

这是方法一的字节码:

public method1()V
   L0
    LINENUMBER 10 L0
    ALOAD 0
    GETFIELD package/SomeClass.myList : Ljava/util/List;
    INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; (itf)
    ASTORE 1
   L1
   FRAME APPEND [java/util/Iterator]
    ALOAD 1
    INVOKEINTERFACE java/util/Iterator.hasNext ()Z (itf)
    IFEQ L2
    ALOAD 1
    INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object; (itf)
    CHECKCAST java/lang/String
    ASTORE 2
   L3
    LINENUMBER 11 L3
    ALOAD 0
    GETFIELD package/SomeClass.myList : Ljava/util/List;
    ALOAD 2
    INVOKEINTERFACE java/util/List.indexOf (Ljava/lang/Object;)I (itf)
    ISTORE 3
   L4
    LINENUMBER 12 L4
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 3
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L5
    LINENUMBER 13 L5
    GOTO L1
   L2
    LINENUMBER 14 L2
   FRAME CHOP 1
    RETURN
   L6
    LOCALVARIABLE index I L4 L5 3
    LOCALVARIABLE key Ljava/lang/String; L3 L5 2
    LOCALVARIABLE this Lpackage/SomeClass; L0 L6 0
    MAXSTACK = 2
    MAXLOCALS = 4

这是方法2的字节码:

public method2()V
   L0
    LINENUMBER 12 L0
    ALOAD 0
    GETFIELD package/SomeClass2.myList : Ljava/util/List;
    INVOKEINTERFACE java/util/List.iterator ()Ljava/util/Iterator; (itf)
    ASTORE 2
   L1
   FRAME APPEND [T java/util/Iterator]
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.hasNext ()Z (itf)
    IFEQ L2
    ALOAD 2
    INVOKEINTERFACE java/util/Iterator.next ()Ljava/lang/Object; (itf)
    CHECKCAST java/lang/String
    ASTORE 3
   L3
    LINENUMBER 13 L3
    ALOAD 0
    GETFIELD package/SomeClass2.myList : Ljava/util/List;
    ALOAD 3
    INVOKEINTERFACE java/util/List.indexOf (Ljava/lang/Object;)I (itf)
    ISTORE 1
   L4
    LINENUMBER 14 L4
    GETSTATIC java/lang/System.out : Ljava/io/PrintStream;
    ILOAD 1
    INVOKEVIRTUAL java/io/PrintStream.println (I)V
   L5
    LINENUMBER 15 L5
    GOTO L1
   L2
    LINENUMBER 16 L2
   FRAME CHOP 2
    RETURN
   L6
    LOCALVARIABLE key Ljava/lang/String; L3 L5 3
    LOCALVARIABLE index I L4 L2 1
    LOCALVARIABLE this Lpackage/SomeClass2; L0 L6 0
    MAXSTACK = 2
    MAXLOCALS = 4

如果您进行 diff(例如 diffchecker),您将看到 BYTECODE IS THE SAME(由编译器优化)- 性能也是如此。

无论如何,正如@erwin-bolwidt 正确指出的那样,性能问题是在 for 循环中使用 indexOf 方法,而不是声明局部变量的地方。

【讨论】:

    猜你喜欢
    • 2014-10-29
    • 2012-06-08
    • 2013-08-04
    • 2020-12-25
    • 2020-05-11
    • 2011-06-13
    • 2019-07-17
    • 1970-01-01
    • 2020-05-30
    相关资源
    最近更新 更多