我注意到 Java String 将在其中重用 char 数组,以避免在 subString() 等方法中为新的 String 实例创建新的 char 数组。为此,String 中有几个 unpublish 构造函数,接受一个 char 数组和两个 int 作为范围来构造一个 String 实例。
但是直到今天我发现split也会重用原始String实例的char arr。现在我从一个文件中读取了一个 loooooong 行,用“,”将其拆分并剪切了一个非常有限的列以供实际使用。因为该行的每一部分都 secret 持有 looooong char 数组的引用,所以我很快得到了一个 OOO。
这里是示例代码:
ArrayList<String> test = new ArrayList<String>(3000000);
BufferedReader origReader = new BufferedReader(new FileReader(new File(
"G:\\filewithlongline.txt")));
String line = origReader.readLine();
int i = 0;
while ((line = origReader.readLine()) != null) {
String name = line.split(',')[0];
test.add(name);
i++;
if (i % 100000 == 0) {
System.out.println(name);
}
}
System.out.println(test.size());
JDK 中是否有任何标准方法来确保吐出的每个 String 实例都是“真正的深拷贝”而不是“浅拷贝”?
现在我正在使用一个非常丑陋的解决方法来强制创建一个新的 String 实例:
ArrayList<String> test = new ArrayList<String>(3000000);
BufferedReader origReader = new BufferedReader(new FileReader(new File(
"G:\\filewithlongline.txt")));
String line = origReader.readLine();
int i = 0;
while ((line = origReader.readLine()) != null) {
String name = line.split(',')[0]+" ".trim(); // force creating a String instance
test.add(name);
i++;
if (i % 100000 == 0) {
System.out.println(name);
}
}
System.out.println(test.size());
最佳答案
最简单的方法是直接创建一个新的String。这是极少数的好主意之一。
String name = new String(line.split(",")[0]); // note the use of ","
另一种方法是自己解析文件。
do {
StringBuilder name = new StringBuilder();
int ch;
while((ch = origReader.read()) >= 0 && ch != ',' && ch >= ' ') {
name.append((char) ch);
}
test.add(name.toString());
} while(origReader.readLine() != null);
关于java - String.split() 将保留原始的 char 数组在里面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12238263/