我正在阅读一个大约有50,000行和1.1MiB大小的csv文件(并且可以变大)。
在Code1中,我使用String来处理csv,而在Code2中我使用StringBuilder(只有一个线程执行代码,所以没有并发问题)
使用StringBuilder使用普通的String类使代码更难阅读。
我是否过早使用Code2中的StringBuilder进行优化以节省一些堆空间和内存?
Code1
fr = new FileReader(file);
BufferedReader reader = new BufferedReader(fr);
String line = reader.readLine();
while ( line != null )
{
int separator = line.indexOf(',');
String symbol = line.substring(0, seperator);
int begin = separator;
separator = line.indexOf(',', begin+1);
String price = line.substring(begin+1, seperator);
// Publish this update
publisher.publishQuote(symbol, price);
// Read the next line of fake update data
line = reader.readLine();
}
代码2
fr = new FileReader(file);
StringBuilder stringBuilder = new StringBuilder(reader.readLine());
while( stringBuilder.toString() != null ) {
int separator = stringBuilder.toString().indexOf(',');
String symbol = stringBuilder.toString().substring(0, separator);
int begin = separator;
separator = stringBuilder.toString().indexOf(',', begin+1);
String price = stringBuilder.toString().substring(begin+1, separator);
publisher.publishQuote(symbol, price);
stringBuilder.replace(0, stringBuilder.length(), reader.readLine());
}
修改
我删除了toString()调用,因此会产生更少的字符串对象。
CODE3
while( stringBuilder.length() > 0 ) {
int separator = stringBuilder.indexOf(",");
String symbol = stringBuilder.substring(0, separator);
int begin = separator;
separator = stringBuilder.indexOf(",", begin+1);
String price = stringBuilder.substring(begin+1, separator);
publisher.publishQuote(symbol, price);
Thread.sleep(10);
stringBuilder.replace(0, stringBuilder.length(), reader.readLine());
}
下载的
答案 0 :(得分:3)
优化代码是否会提高应用程序的性能? - 我的问题
第二个代码示例将不保存任何内存或任何计算时间。我担心你可能误解了StringBuilder
的目的,这本身就是用来构建字符串 - 而不是阅读它们。
在循环或第二个代码示例中,每一行都包含表达式stringBuilder.toString()
,实际上反复将缓冲的字符串转换为String
对象。您的实际字符串操作是针对这些对象完成的。第一个代码示例不仅更容易阅读,而且肯定是两者的兼容性。
我是否过早使用StringBuilder进行优化? - 您的问题
除非您已经对应用程序进行了分析并得出结论,这些行会导致执行速度明显减慢,是。除非你确定某些东西会很慢(例如,如果你认识到高计算复杂性),你肯定希望在开始进行一些损害代码可读性的优化之前进行一些分析。
可以对此代码进行哪些优化? - 我的问题
如果您已对应用程序进行了分析,并确定这是进行优化的正确位置,则应考虑查看Scanner
类提供的功能。实际上,这可能会为您提供更好的性能(分析会告诉您这是否属实)以及更简单的代码。
答案 1 :(得分:2)
我是否过早使用Code2中的StringBuilder进行优化以节省一些堆空间和内存?
最有可能:是。但是,只有一种方法可以找到答案:分析您的代码。
另外,我会使用正确的CSV解析器而不是您现在正在做的事情:http://ostermiller.org/utils/CSV.html
答案 2 :(得分:1)
Code2实际上效率低,因为每次拨打stringBuilder.toString()
时,您都会创建一个新的java.lang.String
实例(除了现有的StringBuilder
宾语)。由于对象创建开销,这在空间和时间方面效率较低。
将readLine()
的内容直接分配给String
,然后将String
分开,通常会有足够的效果。您还可以考虑使用Scanner
类。
内存节省提示
如果在输入中遇到多个重复令牌,请考虑使用String.intern()来确保每个相同的令牌引用相同的String对象; e.g。
String[] tokens = parseTokens(line);
for (String token : tokens) {
// Construct business object referencing interned version of token.
BusinessObject bo = new BusinessObject(token.intern());
// Add business object to collection, etc.
}
答案 3 :(得分:0)
StringBuilder通常使用如下:
StringBuilder sb = new StringBuilder();
sb.append("You").append(" can chain ")
.append(" your ").append(" strings ")
.append("for better readability.");
String myString = sb.toString(); // only call once when you are done
System.out.prinln(sb); // also calls sb.toString().. print myString instead
答案 4 :(得分:0)
StringBuilder有几件好事
StringBuffer和StringBuilder在所有操作中几乎相同,只是StringBuffer已同步且StringBuilder不是
如果你没有多线程,那么最好使用StringBuilder