-2

Which of the loops is faster?

Loop 1

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

Loop 2

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

Thanks for any help. I'm trying to learn some more about performence.

Ziv Sion
  • 165
  • 1
  • 11
  • 6
    _"Which of the loops is faster?"_ - Why don't you run your horses? There's also a chance that the compiler will optimize this to the exact same bytecode ... so, you might want to check that, too. – Fildor Jul 27 '21 at 12:03
  • 5
    Related: [What is microbenchmarking?](https://stackoverflow.com/questions/2842695/what-is-microbenchmarking) – Federico klez Culloca Jul 27 '21 at 12:06
  • What are you trying to achieve with this level of performance measurement? Performance of both shouldn't matter until and unless you have huge data or you have exhausted other optimisations. – Pradeep Simha Jul 27 '21 at 12:17
  • 4
    You're looking in the wrong place to make your code faster. Don't do `myList.indexOf(key)` in every iteration of the loop. Write `int index = 0; for (String key : myList) { System.out.println(index); index++; }` – Erwin Bolwidt Jul 27 '21 at 12:22
  • @ErwinBolwidt that might not give the same result if there are duplicate entries in the list. Unclear which behavior is desired. – Andy Turner Jul 27 '21 at 13:44
  • "I'm trying to learn some more about performence." The most important thing to learn about performance is that the JVM is much better at optimization than you (or any of us). Choose better algorithms, if you can, to do less work; but don't worry about most things until you have proof it's worth worrying about. – Andy Turner Jul 27 '21 at 13:46

1 Answers1

1

Your question is quite "interesting", but OK, here is your answer: You need to check bytecode.

Here is bytecode of method 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

Here is bytecode of method 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

If you do the diff (diffchecker for example), you will see that BYTECODE IS THE SAME (optimized by compiler)- so is the performance.

Anyway, as @erwin-bolwidt correctly noted, performance problem is using indexOf method in for loop, not place of declaring local variable.

Gondy
  • 4,925
  • 4
  • 40
  • 46