Java内存分配
我有一个问题一直在思考。以这个特殊的类为例Java内存分配,java,recursion,stack-overflow,Java,Recursion,Stack Overflow,我有一个问题一直在思考。以这个特殊的类为例 class A{ private static ArrayList<String> listOne; public Static ArrayList<String> getList() { return this.listOne } } A类{ 私有静态ArrayList-listOne; 公共静态ArrayList getList() { 把这个还给我 } } 假设我有一个类B,它拥有一个方法来
class A{
private static ArrayList<String> listOne;
public Static ArrayList<String> getList()
{
return this.listOne
}
}
A类{
私有静态ArrayList-listOne;
公共静态ArrayList getList()
{
把这个还给我
}
}
假设我有一个类B,它拥有一个方法来读取listOne的详细信息。要查看arraylist,我需要首先获得列表的大小,以便代码知道arraylist何时结束。我有两种方法可以做到这一点,一种是
int listSize = A.getList().size()
for(int count =0; count < listSize; count++)
{
// code to read through arraylist
}
int listSize=A.getList().size()
对于(int count=0;count
或者我也可以用它来实现同样的目标
for(int count=0; count < A.getList().size(); count++)
{
// code to read through arraylist
}
for(int count=0;count
在内存和效率方面,哪种方法更好?此外,假设我正在递归地读取一个非常大的数组。为了简单起见,让我们假设递归读取此数组将导致堆栈溢出异常。在这种情况下,第一个方法理论上会导致堆栈溢出发生得比第二个方法更早,因为每个递归调用的堆栈帧必须保持变量“listSize”的状态吗 查看
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;
}
}
import java.io.*;
导入java.util.*;
公共类Z{
公共静态void main(字符串[]args)引发异常{
int listSize=A.getList().size();
对于(int count=0;count
查看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;
}
}
import java.io.*;
导入java.util.*;
公共类Z{
公共静态void main(字符串[]args)引发异常{
int listSize=A.getList().size();
对于(int count=0;count
两个循环都是相同的。第二个是更好的编码,因为它减少了代码行。
既然您提到需要遍历列表,那么最好使用增强的(for each)for循环
两个循环都是相同的。第二个是更好的编码,因为它减少了代码行。
既然您提到需要遍历列表,那么最好使用增强的(for each)for循环
关于哪种方法更有效,我认为它们不会有任何明显的区别。正如Germann所说,根据JVM的不同,编译器甚至会对此进行优化。所以不要担心这个微不足道的差别
我个人将使用第二种方法,因为它的代码行较少,而且我很懒
然而,为什么两者都不使用呢
有一个超级酷的选择,它的名字是。。。乔恩·塞纳是增强型for循环
让我们将其与普通for循环进行比较:
正常:
for (int i = 0 ; i < A.getList().size() ; i++ {
}
看这多好啊
这两个for循环的主要区别在于
- normal for循环只是一种带有初始化和增量的while循环
- 增强的for循环调用
.iterator().hasNext()
和.iterator().next()
- 要使用普通for循环,您需要知道列表的大小
- 您的列表只需要实现
Iterable
,可能还需要实现Iterator
,以使用增强的for循环。不需要尺寸
增强的for循环具有以下限制:
- 不能同时在两个数组中循环
- 如果想知道列表的索引,最好使用普通for循环,因为多次调用
indexOf
不是很有效
关于哪种方法更有效,我认为它们不会有任何明显的区别。正如Germann所说,根据JVM的不同,编译器甚至会对此进行优化。所以不要担心这个微不足道的差别
我个人将使用第二种方法,因为它的代码行较少,而且我很懒
然而,为什么两者都不使用呢
有一个超级酷的选择,它的名字是。。。乔恩·塞纳是增强型for循环
让我们将其与普通for循环进行比较:
正常:
for (int i = 0 ; i < A.getList().size() ; i++ {
}
看这多好啊
这两个for循环的主要区别在于
- normal for循环只是一种带有初始化和增量的while循环
- 增强的for循环调用
.iterator().hasNext()
和.iterator().next()
- 要使用普通for循环,您需要知道列表的大小
- 您的列表只需要实现
Iterable
,可能还需要实现Iterator
,以使用增强的for循环。不需要尺寸
增强的for循环具有以下l