我正在编写一个Java
应用程序来读取大型文本文件,其中数据以字符列的格式表示。例如:
A B R S Y E ...
R E W I W I ...
E Q B U O Y ...
W Q V G O R ...
即。单个字母由空格分隔。 每行都有数百万个这样的字符。每个文件都有几行。
我的工作是按列操作文件。所以我逐行读取文件,在' '
上拆分并创建数组。从这样的数组中,我创建了一个二维数组。一切都很好,因为我在一个小文件上测试它,有10行。但是当我读取500行的文件时,它开始失败了。我的机器和JVM
有很多记忆,所以我没想到这一点。因此,我进行了一些分析,发现将行读入String[]
所占用的内存比预期多得多。因此,我将String[]
更改为char[]
。内存使用量急剧下降,一切都很好。
我的问题是为什么String[]
占用的空间比char[]
多得多?是因为它就像一个对象数组? (因为String也是一个Object)。如果有人可以解释低级细节,那将非常棒。
以前是我以前做的事情:
String[] parts = line.split(" "); // Creating a String[]
这就是我改为:
String rowNoSpaces = line.replaceAll(" ", ""); // Removing all the spaces
char[] columns= rowNoSpaces.toCharArray(); // Creating a char[], instead of String[]
如果需要更多信息,请告诉我。
答案 0 :(得分:10)
由于char
是基本类型,因此字符数组会将这些字节直接存储在数组中,而不会产生每个字符的开销。
相比之下,String
是一个对象,因此数组将存储指向堆中其他位置的String
个实例的指针,每个实例都有自己的vtable,length和&其他信息(包括对char[]
与实际文本的单独引用)。拥有大量对象也会增加GC堆碎片的风险。
此外,如果您通过连接而不是StringBuilder
来构建字符串,那么您还将获得大量额外的副本,从而占用更多内存。