我有一个需要修剪(即所有的空格字符/ u0020及以下的任一端删除)一个StringBuilder对象。
I have a StringBuilder object that needs to be trimmed (i.e. all whitespace chars /u0020 and below removed from either end).
我似乎无法找到一个方法字符串生成器,会做到这一点。
I can't seem to find a method in string builder that would do this.
下面就是我现在做的:
String trimmedStr = strBuilder.toString().trim();
这给出恰好所需的输出,但它需要两个字符串要被分配,而不是一个。有没有更有效的修剪字符串,同时它还是在StringBuilder的?
This gives exactly the desired output, but it requires two Strings to be allocated instead of one. Is there a more efficient to trim the string while it's still in the StringBuilder?
你不应该使用deleteCharAt方法。
由于鲍里斯指出的那样,deleteCharAt方法复制的阵列上每一次。在code在Java 5中,这是否是这样的:
As Boris pointed out, the deleteCharAt method copies the array over every time. The code in the Java 5 that does this looks like this:
public AbstractStringBuilder deleteCharAt(int index) {
if ((index < 0) || (index >= count))
throw new StringIndexOutOfBoundsException(index);
System.arraycopy(value, index+1, value, index, count-index-1);
count--;
return this;
}
当然,
,单靠炒作是不够的,选择优化了另一种方法,所以我决定时间3方法在这个线程:原来,删除方法和子方法
Of course, speculation alone is not enough to choose one method of optimization over another, so I decided to time the 3 approaches in this thread: the original, the delete approach, and the substring approach.
下面是code我测试了一部开拓创新的:
Here is the code I tested for the orignal:
public static String trimOriginal(StringBuilder sb) {
return sb.toString().trim();
}
的删除方法:
The delete approach:
public static String trimDelete(StringBuilder sb) {
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(0))) {
sb.deleteCharAt(0);
}
while (sb.length() > 0 && Character.isWhitespace(sb.charAt(sb.length() - 1))) {
sb.deleteCharAt(sb.length() - 1);
}
return sb.toString();
}
和子串的方法:
public static String trimSubstring(StringBuilder sb) {
int first, last;
for (first=0; first<sb.length(); first++)
if (!Character.isWhitespace(sb.charAt(first)))
break;
for (last=sb.length(); last>first; last--)
if (!Character.isWhitespace(sb.charAt(last-1)))
break;
return sb.substring(first, last);
}
我进行的100次测试,每次产生一百万个字符的StringBuffer一万尾随和前导空格。测试本身是很基本的,但它给的方法多长时间是一个好主意。
I performed 100 tests, each time generating a million-character StringBuffer with ten thousand trailing and leading spaces. The testing itself is very basic, but it gives a good idea of how long the methods take.
下面是code到时间3的方法:
Here is the code to time the 3 approaches:
public static void main(String[] args) {
long originalTime = 0;
long deleteTime = 0;
long substringTime = 0;
for (int i=0; i<100; i++) {
StringBuilder sb1 = new StringBuilder();
StringBuilder sb2 = new StringBuilder();
StringBuilder sb3 = new StringBuilder();
for (int j=0; j<10000; j++) {
sb1.append(" ");
sb2.append(" ");
sb3.append(" ");
}
for (int j=0; j<980000; j++) {
sb1.append("a");
sb2.append("a");
sb3.append("a");
}
for (int j=0; j<10000; j++) {
sb1.append(" ");
sb2.append(" ");
sb3.append(" ");
}
long timer1 = System.currentTimeMillis();
trimOriginal(sb1);
originalTime += System.currentTimeMillis() - timer1;
long timer2 = System.currentTimeMillis();
trimDelete(sb2);
deleteTime += System.currentTimeMillis() - timer2;
long timer3 = System.currentTimeMillis();
trimSubstring(sb3);
substringTime += System.currentTimeMillis() - timer3;
}
System.out.println("original: " + originalTime + " ms");
System.out.println("delete: " + deleteTime + " ms");
System.out.println("substring: " + substringTime + " ms");
}
我得到了以下的输出:
I got the following output:
original: 176 ms
delete: 179242 ms
substring: 154 ms
正如我们看到的,子方式提供了原来的两个String的做法非常轻微的优化。但是,删除的方法是极其缓慢的,应该避免。
As we see, the substring approach provides a very slight optimization over the original "two String" approach. However, the delete approach is extremely slow and should be avoided.
因此,要回答你的问题:你是精细修剪你的StringBuilder你的问题建议的方式。非常轻微的优化,该子方法提供了可能并不能证明过量code。
So to answer your question: you are fine trimming your StringBuilder the way you suggested in the question. The very slight optimization that the substring method offers probably does not justify the excess code.