Я знаю, что мы можем добавлять строки, используя StringBuilder
. Есть ли способ, которым мы можем добавлять строки (т.е. Добавлять строки перед строкой) с помощью StringBuilder
, чтобы мы могли сохранить преимущества производительности, которые предлагает StringBuilder
?
С# или Java: предустановить строки с помощью StringBuilder?
Ответ 1
Использование метода вставки с параметром позиции, установленным в 0, будет таким же, как предварительное добавление (то есть вставка в начале).
Пример: varStringBuilder.insert(0, "someThing");
Ответ 2
Предварительная подготовка строки, как правило, требует копирования всего после точки вставки обратно в массив подстановки, поэтому она не будет такой быстрой, как добавление к концу.
Но вы можете сделать это так на Java (в С# это то же самое, но метод называется Insert
):
aStringBuilder.insert(0, "newText");
Ответ 3
Если вам требуется высокая производительность с большим количеством добавок, вам нужно написать собственную версию StringBuilder
(или использовать чужой). Со стандартным StringBuilder
(хотя технически он может быть реализован по-разному) вставка требует копирования данных после точки вставки. Вставка n фрагмента текста может занять время O (n ^ 2).
Наивный подход заключается в добавлении смещения в буфер резервного копирования char[]
, а также в длину. Если места для префикса недостаточно, переместите данные более, чем это необходимо. Это может привести к снижению производительности до O (n log n) (я думаю). Более совершенный подход состоит в том, чтобы сделать буфер циклическим. Таким образом, запасное пространство на обоих концах массива становится смежным.
Ответ 4
Вы можете попробовать метод расширения:
/// <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!
Ответ 5
Вот что вы можете сделать, если хотите добавить в начало класс Java StringBuilder:
StringBuilder str = new StringBuilder();
str.Insert(0, "text");
Ответ 6
Я не использовал его, но Веревки для Java Звучит интригующе. Название проекта - игра слов, для серьезной работы используйте веревку вместо строки. Получает ограничение производительности для дополнительных операций и других операций. Стоит посмотреть, если вы собираетесь делать это много.
Канат - это высокая производительность замена для строк. datastructure, подробно описанной в "Веревки: альтернатива струнам", обеспечивает асимптотически лучшее чем как String, так и StringBuffer для общей строки такие как prepend, append, удалить и вставить. Как струны, канаты неизменны и поэтому хорошо подходит для использования в многопоточных программирование.
Ответ 7
Вы можете построить строку в обратном порядке и затем отменить результат. Вы берете на себя стоимость O (n) вместо стоимости наихудшего случая O (n ^ 2).
Ответ 8
Если вы правильно поняли, метод выглядит так, как будто он будет делать то, что вы хотите. Просто вставьте строку со смещением 0.
Ответ 9
Попробуйте использовать Insert()
StringBuilder MyStringBuilder = new StringBuilder("World!");
MyStringBuilder.Insert(0,"Hello "); // Hello World!
Ответ 10
Судя по другим комментариям, нет стандартного быстрого способа сделать это. Использование StringBuilder .Insert(0, "text")
примерно в 1-3 раза быстрее, чем использование мучительно медленной конкатенации строк (на основе > 10000 concats), поэтому ниже - класс, который может быть добавлен в тысячи раз быстрее!
Я включил некоторые другие базовые функции, такие как 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)
}
}
Ответ 11
Вы можете создать расширение для 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, и в любое время, когда вы используете intelli-sense с переменной StringBuilder, появятся методы Prepend и PrependLine. Просто помните, что когда вы используете Prepend, вам нужно будет предусмотреть в обратном порядке, чем если бы вы добавляли.
Ответ 12
Это должно работать:
aStringBuilder = "newText" + aStringBuilder;