我在android上制作一个字典应用程序。在启动期间,应用程序将加载.index文件的内容(~2MB,100.000+行)
但是,当我使用BufferedReader.readLine()并对返回的字符串执行某些操作时,应用程序将导致OutOfMemory。
// Read file snippet
Set<String> indexes = new HashSet<String)();
FileInputStream is = new FileInputStream(indexPath);
BufferedReader reader = new BufferedReader(new InputStreamReader(is));
String readLine;
while ( (readLine = reader.readLine()) != null) {
indexes.add(extractHeadWord(readLine));
}
// And the extractHeadWord method
private String extractHeadWord(String string) {
String[] splitted = string.split("\\t");
return splitted[0];
}
当读取日志时,我发现在执行时,它会导致GC多次显式清理对象(GC_EXPLICIT释放了xxx对象,其中xxx是一个很大的数字,如15000,20000)。
我尝试了另一种方式:
final int BUFFER = 50;
char[] readChar = new char[BUFFER];
//.. construct BufferedReader
while (reader.read(readChar) != -1) {
indexes.add(new String(readChar));
readChar = new char[BUFFER];
}
..它运行得非常快。但这并不是我想要的。
是否有任何解决方案作为第二个代码段快速运行并且易于使用?
方面。
答案 0 :(得分:4)
extractHeadWord
使用String.split
方法。此方法不会创建新字符串,而是依赖于基础字符串(在您的情况下为line
对象)并使用索引指出“新”字符串。
由于你没有在字符串的其余部分中处理它,你需要丢弃它以便它被垃圾收集,否则整个字符串将在内存中(但你只使用它的一部分)。
调用构造函数String(String)
(“复制构造函数”)会丢弃其余的字符串:
private String extractHeadWord(String string) {
String[] splitted = string.split("\\t");
return new String(splitted[0]);
}
答案 1 :(得分:3)
如果extractHeadWord
执行此操作return new String(splitted[0]);
,会发生什么情况。
它不会减少临时对象,但可能会减少应用程序的占用空间。我不知道split是否和substring一样,但我猜它确实如此。 substring在原始数据上创建一个新视图,这意味着完整的字符数组将保留在内存中。显式调用new String(string)
将截断数据。