如何修剪一个Java的StringBuilder?Java、StringBuilder

2023-09-06 07:59:37 作者:狗屎碍人@!

我有一个需要修剪(即所有的空格字符/ 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.