0

I have a question that i have been pondering for a while. Take for instance this particular piece of class

class A{

private static ArrayList<String> listOne;

public Static ArrayList<String> getList()
  {
    return this.listOne
  }
}  

Let say i have class B that possess a method to read the details with listOne. To Look through the arraylist, i would need to first get the size of the list in order for my code to know when the arraylist ends. There are 2 ways in which i can do so, one being

int listSize = A.getList().size()
for(int count =0; count < listSize; count++)
{
  // code to read through arraylist
}

or i can achieve the same thing with

for(int count=0; count < A.getList().size(); count++)
{
  // code to read through arraylist
}

In terms of memory and efficiency, which method is better? Furthermore let says i am reading through a very large array recursively. For simplicity purposes, lets assume that recursively reading through this array would a stack overflow exception. In this situation, would the first method theoretically cause a stack overflow to happen earlier then the second method seeing that each recursive call's stack frame has to keep the state of the variable "listSize"?

weejing
  • 173
  • 2
  • 12
  • 1
    You can also use enhanced for loop. – theVoid Jun 05 '16 at 10:04
  • 2
    Use enhanced for loop `for(String elements : A.getList()) { //body }` – Vishal Vijayan Jun 05 '16 at 10:06
  • It will depend on your usage of `listSize`, in many cases JVM will remove this assignment completely during optimisation. Even if it does not the chances that your stack will get overflowed by an `int` value are really minimal. – Germann Arlington Jun 05 '16 at 10:15
  • @GermannArlington Note (assuming non-optimzed version) that it actually would be an `int` *per* recursive call. – dingalapadum Jun 05 '16 at 10:41
  • @weejing I think *theoretically* you are right that the stackoverflow-exception might happen a few calls earlier. But I don't think it would happen *much* earlier. However, if a stackoverflow-exception is within reach in your task, I would avoid recursion altogether. – dingalapadum Jun 05 '16 at 10:42
  • @dingalapadum Exactly, there is a lot more info being stored per recursion call, so the chances of the `int` causing a problem are minimal – Germann Arlington Jun 05 '16 at 16:33

3 Answers3

2

Have a look at the result of javap -verbose:

 0: invokestatic  #2                  // Method A.getList:()Ljava/util/ArrayList;
 3: invokevirtual #3                  // Method java/util/ArrayList.size:()I
 6: istore_1
 7: iconst_0
 8: istore_2
 9: iload_2
10: iload_1
11: if_icmpge     27
14: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
17: iload_2
18: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
21: iinc          2, 1
24: goto          9
27: iconst_0
28: istore_2
29: iload_2
30: invokestatic  #2                  // Method A.getList:()Ljava/util/ArrayList;
33: invokevirtual #3                  // Method java/util/ArrayList.size:()I
36: if_icmpge     52
39: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
42: iload_2
43: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
46: iinc          2, 1
49: goto          29
52: return

First case is:

 9: iload_2
10: iload_1
11: if_icmpge     27
14: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
17: iload_2
18: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
21: iinc          2, 1
24: goto          9

And the second one:

29: iload_2
30: invokestatic  #2                  // Method A.getList:()Ljava/util/ArrayList;
33: invokevirtual #3                  // Method java/util/ArrayList.size:()I
36: if_icmpge     52
39: getstatic     #4                  // Field java/lang/System.out:Ljava/io/PrintStream;
42: iload_2
43: invokevirtual #5                  // Method java/io/PrintStream.println:(I)V
46: iinc          2, 1
49: goto          29

As you can see, it will get the list and its size during each loop iteration. But, this might be optimized by JIT, so the result is not obvious from just the compiled bytecode.

Created from:

import java.io.*;
import java.util.*;

public class Z {

    public static void main(String[] args) throws Exception {
        int listSize = A.getList().size();
        for(int count =0; count < listSize; count++) {
            System.out.println(count);
        }
        for(int count =0; count < A.getList().size(); count++) {
            System.out.println(count);
        }
    }

}

class A{

    private static ArrayList<String> listOne = new ArrayList<>(Arrays.asList("1", "2", "3"));

    public static ArrayList<String> getList()
    {
        return listOne;
    }
}  
Krzysztof Krasoń
  • 26,515
  • 16
  • 89
  • 115
1

Both the loop are same. Second one is better coding as it reduces line of code. Since you mentioned that your need is to traverse the list it is much better to use the enhanced (for-each) for loop.

What are the Advantages of Enhanced for loop and Iterator in Java?

why is enhanced for loop efficient than normal for loop

Community
  • 1
  • 1
Vishal Vijayan
  • 308
  • 1
  • 4
  • 13
0

Regarding which of the method is more efficient, I think they won't have any noticeable differences. And depending on the JVM, like Germann has said, the compiler will even optimize this. So just don't worry about this negligible difference.

I personally will use the second method since it has fewer lines of code and I'm lazy...

However, why not use neither?

There's a super cool alternative, and its name is... JON CENA The enhanced for loop.

Let's compare it with a normal for loop:

Normal:

for (int i = 0 ; i < A.getList().size() ; i++ {

}

Enhanced:

for (String item : A.getList()) {
    // Instead of using A.getList().get(i) to access the items, just use "item"!
}

Look how nice it is!

The major difference between these two for loops is that

  • The normal for loop is just a kind of a while loop with initialization and incrementation.
  • The enhanced for loop calls .iterator().hasNext() and .iterator().next() to loop.
  • You need to know the size of the list to use a normal for loop
  • Your list just needs to implement Iterable and probably Iterator to use an enhanced for loop. No size is needed.

An enhanced for loop has the following limitations:

  • You can't loop through two arrays at the same time
  • It's better to use a normal for loop if you want to know the index of the list, since calling indexOf a lot of times is not very efficient.
Sweeper
  • 213,210
  • 22
  • 193
  • 313