2009-04-10 35 views
82

我知道我们可以使用StringBuilder附加字符串。有没有一种方法可以使用StringBuilder预先安装字符串(即在字符串前添加字符串),以便我们可以保持StringBuilder提供的性能优势?C#或Java:用StringBuilder预加字符串?

+0

我不明白你的问题 – 2009-04-10 21:41:45

+5

Prepend。这个词是prepend。预先出现的字符串必须是一次性添加到字符串的两端,我猜? – 2009-04-11 23:38:38

回答

119

使用位置参数设置为0的插入方法与预先挂接相同(即在开始时插入)。

这既适用C#Java

+7

针对java的StringBuilder插入:http://java.sun.com/j2se/1.5.0/docs/api/java/lang/StringBuilder.html#insert(int,%20boolean) – 2009-04-12 16:21:41

+0

相关API的正确JavaDoc是:http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/StringBuilder.html#insert(int,%20java.lang.CharSequence%29 – ArtB 2012-02-28 19:12:14

5
StringBuilder str = new StringBuilder(); 
str.Insert(0, "text"); 

编辑:格式化代码

2

尝试使用Insert()

StringBuilder MyStringBuilder = new StringBuilder("World!"); 
MyStringBuilder.Insert(0,"Hello "); // Hello World! 
23

前面加上一个字符串,通常需要将所有内容复制将插入点向后一些后在后备数组中,所以它不会像追加到最后一样快。

但是你可以在Java中像下面这样做(在C#这是相同的,但该方法被称为Insert):

aStringBuilder.insert(0, "newText"); 
4

如果我理解正确的话,则insert method看起来像它会做什么你要。只需插入串在偏移0

5

你可以尝试扩展方法:

/// <summary> 
/// kind of a dopey little one-off for StringBuffer, but 
/// an example where you can get crazy with extension methods 
/// </summary> 
public static void Prepend(this StringBuilder sb, string s) 
{ 
    sb.Insert(0, s); 
} 

StringBuilder sb = new StringBuilder("World!"); 
sb.Prepend("Hello "); // Hello World! 
10

如果你需要有大量的预规划的高性能,你需要编写自己的StringBuilder版本(或使用别人的)。使用标准StringBuilder(虽然在技术上可以以不同的方式实现)插入要求在插入点之后复制数据。插入n段文字可能需要O(n^2)次。

一个简单的方法是在后备char[]缓冲区中添加一个偏移量以及长度。如果没有足够的空间进行预设,请将数据向上移动超过绝对必要的数量。这可以使性能回到O(n log n)(我认为)。更精细的方法是使缓冲区循环。这样阵列两端的备用空间变得连续。

5

我没有使用它,但Ropes For Java听起来有趣。该项目的名称是一个玩的话,使用而不是字符串认真的工作。获取前置和其他操作的性能损失。值得一看,如果你将要做很多这样的事情。

一根绳子是高性能 替代字符串。的数据结构 ,中详细描述 “绳索:一种替代字符串”, 提供比字符串和 StringBuffer的渐近更好 性能以便共同串 修改诸如prepend,追加,删除 ,并插入。像字符串一样, 绳索是不可变的,因此 非常适合用于多线程 编程。

5

您可以反向构建字符串,然后反转结果。 您将承担O(n)成本,而不是O(n^2)最差成本。

+2

这只适用于如果你追加个人字符,否则你需要将每个字符串反过来,如果不是所有的节省量,都会根据字符串的大小和数量来消耗大部分存储空间。 – ArtB 2012-04-26 18:10:31

2

从其他评论来看,没有标准的快速方法来做到这一点。使用StringBuilder的.Insert(0, "text")大约只有使用痛苦的慢字符串连接(基于> 10000连接)的速度快1-3倍,所以下面是一个类,可能需要数千次更快!

我已经包括了其他一些基本功能,如append()subString()length()等等都附加,并预置约两倍的速度变化3倍慢于StringBuilder的追加。像StringBuilder一样,当文本溢出旧的缓冲区大小时,该类中的缓冲区将自动增加。

该代码已经过相当多的测试,但我不能保证它没有错误。

class Prepender 
{ 
    private char[] c; 
    private int growMultiplier; 
    public int bufferSize;  // Make public for bug testing 
    public int left;   // Make public for bug testing 
    public int right;   // Make public for bug testing 
    public Prepender(int initialBuffer = 1000, int growMultiplier = 10) 
    { 
     c = new char[initialBuffer]; 
     //for (int n = 0; n < initialBuffer; n++) cc[n] = '.'; // For debugging purposes (used fixed width font for testing) 
     left = initialBuffer/2; 
     right = initialBuffer/2; 
     bufferSize = initialBuffer; 
     this.growMultiplier = growMultiplier; 
    } 
    public void clear() 
    { 
     left = bufferSize/2; 
     right = bufferSize/2; 
    } 
    public int length() 
    { 
     return right - left; 
    } 

    private void increaseBuffer() 
    { 
     int nudge = -bufferSize/2; 
     bufferSize *= growMultiplier; 
     nudge += bufferSize/2; 
     char[] tmp = new char[bufferSize]; 
     for (int n = left; n < right; n++) tmp[n + nudge] = c[n]; 
     left += nudge; 
     right += nudge; 
     c = new char[bufferSize]; 
     //for (int n = 0; n < buffer; n++) cc[n]='.'; // For debugging purposes (used fixed width font for testing) 
     for (int n = left; n < right; n++) c[n] = tmp[n]; 
    } 

    public void append(string s) 
    { 
     // If necessary, increase buffer size by growMultiplier 
     while (right + s.Length > bufferSize) increaseBuffer(); 

     // Append user input to buffer 
     int len = s.Length; 
     for (int n = 0; n < len; n++) 
     { 
      c[right] = s[n]; 
      right++; 
     } 
    } 
    public void prepend(string s) 
    { 
     // If necessary, increase buffer size by growMultiplier 
     while (left - s.Length < 0) increaseBuffer();    

     // Prepend user input to buffer 
     int len = s.Length - 1; 
     for (int n = len; n > -1; n--) 
     { 
      left--; 
      c[left] = s[n]; 
     } 
    } 
    public void truncate(int start, int finish) 
    { 
     if (start < 0) throw new Exception("Truncation error: Start < 0"); 
     if (left + finish > right) throw new Exception("Truncation error: Finish > string length"); 
     if (finish < start) throw new Exception("Truncation error: Finish < start"); 

     //MessageBox.Show(left + " " + right); 

     right = left + finish; 
     left = left + start; 
    } 
    public string subString(int start, int finish) 
    { 
     if (start < 0) throw new Exception("Substring error: Start < 0"); 
     if (left + finish > right) throw new Exception("Substring error: Finish > string length"); 
     if (finish < start) throw new Exception("Substring error: Finish < start"); 
     return toString(start,finish); 
    } 

    public override string ToString() 
    { 
     return new string(c, left, right - left); 
     //return new string(cc, 0, buffer);  // For debugging purposes (used fixed width font for testing) 
    } 
    private string toString(int start, int finish) 
    { 
     return new string(c, left+start, finish-start); 
     //return new string(cc, 0, buffer);  // For debugging purposes (used fixed width font for testing) 
    } 
} 
0

这应该工作:

aStringBuilder = "newText" + aStringBuilder; 
+0

在.NET中,这与'string'类型的值完全匹配,但不适用于StringBuilder类型的值。@ScubaSteve的答案很好。 – Contango 2014-10-03 12:22:34

1

你可以创建StringBuilder的自己的扩展有一个简单的类:

namespace Application.Code.Helpers 
{ 
    public static class StringBuilderExtensions 
    { 
     #region Methods 

     public static void Prepend(this StringBuilder sb, string value) 
     { 
      sb.Insert(0, value); 
     } 

     public static void PrependLine(this StringBuilder sb, string value) 
     { 
      sb.Insert(0, value + Environment.NewLine); 
     } 

     #endregion 
    } 
} 

然后,只需添加:

using Application.Code.Helpers; 

到任何你想使用的课程的顶部在任何时候使用StringBuilder变量的SenseBuilder,Prepend和PrependLine方法都会显示出来。请记住,当您使用“前置”时,您需要按照与“正在追加”相反的顺序进行预置。

相关问题