java – String.split()将原始的char数组保留在里面
作者:互联网
我注意到Java String会在其中重用char数组,以避免在诸如subString()之类的方法中为新的String实例创建新的char数组.为此,String中有几个取消发布的构造函数,接受一个char数组和两个int作为范围来构造一个String实例.
但直到今天我发现split还将重用原始String实例的char arr.现在我从一个文件中读取一个loooooong行,用“,”拆分它,并为实际用法剪切一个极限列.因为线的每个部分都秘密地拿着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,deep-copy,substring 来源: https://codeday.me/bug/20190901/1786075.html