我有一个问题,我一直在思考。比如这个特定的课程
class A{
private static ArrayList<String> listOne;
public Static ArrayList<String> getList()
{
return this.listOne
}
}
假设我有一个B类,它拥有一个用listOne读取细节的方法。要查看arraylist,我需要首先获取列表的大小,以便我的代码知道arraylist何时结束。有两种方法我可以这样做,一种是
int listSize = A.getList().size()
for(int count =0; count < listSize; count++)
{
// code to read through arraylist
}
或者我可以用
实现同样的目的for(int count=0; count < A.getList().size(); count++)
{
// code to read through arraylist
}
在内存和效率方面,哪种方法更好?此外,我说我正在递归地读取一个非常大的数组。为简单起见,我们假设递归读取此数组会导致堆栈溢出异常。在这种情况下,第一种方法理论上会导致堆栈溢出更早发生,然后第二种方法看到每个递归调用的堆栈帧必须保持变量的状态&#34; listSize&#34;?
答案 0 :(得分:2)
查看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
第一种情况是:
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
第二个:
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
如您所见,它将在每次循环迭代期间获取列表及其大小。 但是,这可能是由JIT优化的,因此结果并不仅仅是编译后的字节码。
创建自:
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;
}
}
答案 1 :(得分:1)
两个循环都是一样的。第二个是更好的编码,因为它减少了代码行。 既然你提到你需要遍历列表,那么使用增强(for-each)for循环要好得多。
What are the Advantages of Enhanced for loop and Iterator in Java?
答案 2 :(得分:0)
关于哪种方法更有效,我认为它们不会有任何明显的差异。依赖于JVM,就像Germann所说,编译器甚至会对此进行优化。所以,不要担心这种微不足道的差异。
我个人会使用第二种方法,因为它的代码行数较少而且我很懒...
然而,为什么不使用?
有一个非常酷的选择,它的名字是...... JON CENA 增强的for循环。
让我们将它与正常的循环进行比较:
正常:
for (int i = 0 ; i < A.getList().size() ; i++ {
}
增强型:
for (String item : A.getList()) {
// Instead of using A.getList().get(i) to access the items, just use "item"!
}
看起来真好!
这两个for循环之间的主要区别是
.iterator().hasNext()
和.iterator().next()
循环。Iterable
,可能Iterator
来使用增强的for循环。不需要任何尺寸。增强的for循环具有以下限制:
indexOf
效率不高。