Строки в c#. String \ StringBuilder
По возможности ответьте с примерами. Заранее спасибо за ответ.
Отслеживать
задан 17 авг 2015 в 10:18
522 7 7 серебряных знаков 16 16 бронзовых знаков
2 ответа 2
Сортировка: Сброс на вариант по умолчанию
String — это строки. Они неизменяемые т.е. конкретную строку нельзя подправить/дописать/укоротить. Любые операции над строками приводят к созданию новой строки (с копированием всего текста). При этом старая строка уходит в мусор (если у вас не остается на нее ссылки).
Так сделано из соображений
- Экономии памяти — не надо подстраховываться и копировать строку «на всякий случай» при передаче куда-то в другой метод. Он ее точно никак не испортит.
- Производительности — можно высчитывать хэш строки один раз, и не заморачиваться с поддержанием его актуальности. Это дает быстрые сравнения строк на равенство (особенно если строки разные).
- Безопасности — код может спокойно работать с пришедшими извне строками, не опасаясь что кто-то влезет в строку по дороге.
- Простоты работы с несколькими потоками — нет проблемы одновременных изменений.
Соответственно, при сборке большой строки из многих маленких эта особенность — неизменяемость строк — приводит к множественному копированию данных и к генерации большого количества мусора.
Для решения этой проблемы есть класс StringBuilder . Это не «строка», а класс для сборки строк из кусков, позволяющий в конце получить результирующую строку вызовом StringBuilder.ToString() .
- Если вам надо просто работать со строками — используете String
- Если вам надо собрать одну большую строку из пачки маленьких — используете StringBuilder
Класс StringBuilder . Методы класса StringBuilder . Примеры
Как известно, в языке программирования C# для работы со строками введен тип string , который соответствует классу System.String или String . Однако, при интенсивной работе со строками более целесообразно использовать класс System.Text.StringBuilder , который обеспечивает более высокую производительность в сравнении с классом String .
Отличие между классами String и StringBuilder состоит в следующем.
В случае с классом String , когда выполняется операция присваивания =
// выделение памяти для строчного литерала "Text1" string s = "Text1"; // перераспределение памяти (выделение нового участка) s = "Text2";
память для нового строчного литерала ( «Text2» ) перераспределяется по новому: выделяется новый участок памяти, в который копируется новая измененная строка. Память, выделенная под предыдущий фрагмент, в дальнейшем уничтожается сборщиком мусора (Garbage collector).
В классе StringBuilder при изменении строки-оригинала, память для новой строки выделяется только в случае, когда размер новой строки больше размера строки-оригинала. При этом, памяти выделяется в два раза больше предыдущего размера. Если размер новой строки меньше или равен размеру строки-оригинала, то память не перераспределяется. Такой механизм позволяет повысить быстродействие за счет уменьшения интенсивности (количества) выделения новых ресурсов и освобождения использованных ресурсов.
Вывод: при интенсивной работе со строками рекомендуется использовать класс StringBuilder , в других случаях рекомендуется использовать класс String (или string ).
2. В каком пространстве имен объявлен класс StringBuilder ?
Чтобы использовать сокращенное имя класса StringBuilder нужно предварительно подключить пространство имен System.Text
using System.Text;
Однако, можно непосредственно обращаться к имени класса с помощью строки System.Text.StringBuilder .
3. Операция присваивания = для класса StringBuilder
В классе System.Text.StringBuilder оператор присваивания не определен. Поэтому, при объявлении объекта класса StringBuilder
StringBuilder sb = new StringBuilder();
использовать оператор присваивания = для присваивания объекту значения
sb = "Hello world!"; // Ошибка компиляции
не удастся. В этом случае компилятор выдаст ошибку
Cannot implicitly convert type 'string' to System.String.StringBuilder
4. Операция присваивания одиночного символа по индексу в классах String и StringBuilder
Между классами System.String и System.Text.StringBuilder существует отличие при использовании операции присваивания по индексу одиночного символа.
Переменной (объекту) типа String нельзя присваивать одиночный символ по индексу как показано ниже
string s = "Some text"; s[5] = 'n'; // ошибка компиляции
Одиночный символ можно только прочитать
string s = "Some text"; char c = s[5]; // работает, c = 't'
В отличие от типа String , для типа StringBuilder отдельный символ может быть изменен по его индексу. Например
StringBuilder sb = new StringBuilder("Some text"); sb[5] = 'n'; // работает
5. Создание объекта класса StringBuilder . Примеры
Класс StringBuilder имеет несколько конструкторов, которые выделяют память а также инициализируют экземпляры этого класса. Ниже приведены примеры создания экземпляров класса (объектов) StringBuilder
using System.Text; . // 1. Создание объекта класса StringBuilder StringBuilder sb1 = new StringBuilder(); StringBuilder sb2 = new StringBuilder(10); // строка, длиной до 10 символов StringBuilder sb3 = new StringBuilder("Hello world!"); // константная строка .
6. Методы класса StringBuilder
В данном разделе рассмотрены методы класса StringBuilder , используемые наиболее часто.
6.1. Метод Append() . Добавить данные к текущему экземпляру
Метод Append() предназначен для добавления копии экземпляра некоторого типа к текущему экземпляру. Метод имеет много перегруженных реализаций для разных типов.
Ниже приведены примеры некоторых реализаций метода Append() .
// Метод Append() - добавить данные любого из стандартных типов // 1. Добавить строку типа string StringBuilder sb = new StringBuilder("Hello "); sb.Append("world!"); Console.WriteLine("sb = ", sb); // sb = Hello world! // 2. Добавить строку типа StringBuilder StringBuilder sb2 = new StringBuilder("abc"); StringBuilder sb3 = new StringBuilder("def"); sb2.Append(sb3); Console.WriteLine("sb2 = ", sb2); // sb2 = abcdef // 3. Добавить число типа double StringBuilder sb4 = new StringBuilder("Pi color: #0000ff;">double Pi = 3.141592; sb4.Append(Pi); Console.WriteLine("", sb4); // Pi = 3.141592 // 4. Добавить переменную типа bool StringBuilder sb5 = new StringBuilder(); sb5.Append(true); Console.WriteLine("sb5 = ", sb5); // sb5 = True
6.2. Изменение отдельного символа в строке. Доступ по индексу
В отличие от типа string , в классе StringBuilder можно изменять отдельный символ по его индексу. Например.
// Изменить отдельный символ строки можно в отличие от типа String StringBuilder sb = new StringBuilder("Text."); sb[0] = 'N'; Console.WriteLine("sb = ", sb); // sb = Next.
6.3. Метод Insert() . Вставка строки в заданную позицию
Метод Insert() предназначен для вставки объектов разных типов в заданную позицию строки. Метод имеет много перегруженных реализаций. Во всех реализациях первый параметр метода задает позицию вставки.
Пример.
// Метод Insert() - вставка данных в исходную строку из заданной позиции // 1. Вставка объекта типа string StringBuilder sb1 = new StringBuilder("abcdef"); StringBuilder sb2 = sb1.Insert(1, "---"); Console.WriteLine("sb1 = ", sb1); // sb1 = a---bcdef Console.WriteLine("sb2 = ", sb2); // sb2 = a-- - bcdef // 2. Вставка объекта типа int StringBuilder sb3 = new StringBuilder("Max = "); sb3.Insert(sb3.Length, "256"); Console.WriteLine("", sb3); // Max = 256 // 3. Вставка объекта типа double StringBuilder sb4 = new StringBuilder(); sb4.Insert(0, Math.PI); Console.WriteLine("Pi = ", sb4); // Pi = 3.141592653589793
6.4. Метод Remove() . Удаление из исходной строки диапазона символов
Метод Remove() используется для удаления из заданной строки диапазона символов начиная с заданной позиции. Метод получает два целочисленных параметра. Первый параметр указывает индекс начала, из которого удаляется строка. Второй параметр указывает количество удаляемых символов.
Пример.
// Метод Remove() - удаляет из исходной строки диапазон символов StringBuilder sb = new StringBuilder("abcdefghi"); sb.Remove(2, 3); // удалить "cde" Console.WriteLine("sb = ", sb); // sb = abfghi StringBuilder sb2 = new StringBuilder("01234567890"); sb2.Remove(0, 5); Console.WriteLine("sb2 = ", sb2); // sb2 = 567890
6.5. Метод Replace() . Заменяет символ/подстроку в исходной строке
Метод Replace() используется для замены подстроки в строке. Метод работает как для одиночных символов так и для строк. Метод имеет несколько перегруженных реализаций, среди которых выделяются четыре нижеследующие:
- замена одного символа типа char на другой символ типа char ;
- замена одного символа типа char на другой символ типа char начиная с заданной позиции и в заданном диапазоне;
- замена одной строки типа string на другую строку типа string ;
- замена одной строки типа string на другую строку типа string начиная с заданной позиции и в заданном диапазоне.
Пример.
// Метод Replace() - заменяет символ/подстроку в исходной строке // на заданный символ/подстроку // 1. Реализация Replace(char, char) - замена одного символа на другой StringBuilder sb = new StringBuilder("Solution"); sb.Replace('o', '+'); Console.WriteLine("sb = ", sb); // sb = S+luti+n // 2. Реализация Replace(char, char, int, int) StringBuilder sb2 = new StringBuilder("0123456789"); // Замена символа '2' на '0' // просмотр строки начинается с позиции 0 до позиции 3 sb2.Replace('2', '+', 0, 3); // sb2 = 01+3456789 Console.WriteLine("sb2 = ", sb2); // Записать в строку новое значение sb2.Clear(); sb2.Insert(0, "200+20+2=222"); // заменить в строке все символы '2' на символы '3' sb2.Replace('2', '3', 0, sb2.Length); Console.WriteLine("sb2 = ", sb2); // sb2 = 300+30+3=333 // 3. Реализация Replace(string, string) StringBuilder sb3 = new StringBuilder("abcdef abcdef"); sb3.Replace("bcd", "AAA"); // заменить все вхождения "bcd" на "AAA" Console.WriteLine("sb3 = ", sb3); // sb3 = aAAAef aAAAef // 4. Реализация Replace(string, string, int, int) StringBuilder sb4 = new StringBuilder("Hello Hello Hello"); sb4.Replace("Hello", "ABC", 0, sb4.Length); Console.WriteLine("sb4 = ", sb4); // sb4 = ABC ABC ABC sb4.Clear(); sb4.Append("1++2++3++4++5"); sb4.Replace("++", "--", 0, 7); // в диапазоне от 0 до 7 Console.WriteLine("sb4 = ", sb4); // sb4 = 1--2--3++4++5
6.6. Метод Clear() . Очистка строки
Метод Clear() реализует очистку строки (удаление всех символов в строке).
Пример.
// Метод Clear() - очистка строки StringBuilder sb = new StringBuilder("This is a string."); Console.WriteLine("sb = ", sb); // sb = This is a string. // очистить строку sb.Clear(); Console.WriteLine("sb = ", sb); // sb =
6.7. Метод CopyTo() . Копировать строку в массив типа char
Метод CopyTo() копирует символы из исходной строки в массив типа char ( System.Char ). Метод получает 4 параметра, которые имеют следующее назначение:
- позиция в исходной строке (тип int );
- массив-назначение (тип char[] ) в который посимвольно записываются символы исходной строки;
- позиция в массиве-назначении (тип int ) из которой начинается копирование символов из исходной строки;
- количество символов, которые копируются (тип int ).
Пример.
// Метод CopyTo() - копирует символы исходной строки в массив типа Char StringBuilder sb = new StringBuilder("abcdef"); char[] arr = new char[5]; // выделить память для массива arr // скопировать фрагмент "bcd" в arr // Параметры: // 1 - исходная позиция в строке sb; // arr - массив-назначение в который копируются символы // 0 - позиция в arr, из которой записываются символы из sb // 3 - количество символов, которые копируются из sb в arr sb.CopyTo(1, arr, 0, 3); // arr = // скопировать фрагмент "cdef" в arr2 char[] arrC2 = new char[6]; sb.CopyTo(2, arrC2, 2, 4); // arrC2 = // Вывести строку arr2[] for (int i = 0; i < arrC2.Length; i++) < Console.WriteLine("arrc[] = ", i, arrC2[i]); >
6.8. Метод ToString() . Конвертировать строку типа StringBuilder в строку типа String
Для конвертирования строки типа StringBuilder в строку типа String используется метод ToString() , который реализован в классе System.Object .
Согласно документации .NET Framework метод ToString() имеет две реализации общая форма которых следующая:
public override string ToString() public string ToString(int startIndex, int length)
В первой реализации происходит простое конвертирование строки типа StringBuilder в строку типа String . Во второй реализации копируется строка начиная с позиции startIndex длиной length символов.
Пример.
// Метод ToString() - конвертирует объект типа StringBuilder в String StringBuilder sb = new StringBuilder("Hello world!"); // Конвертирование строки полностью String s1 = sb.ToString(); Console.WriteLine("s1 = ", s1); // s1 = "Hello world!" // Конвертирование строки начиная с позиции 6, // количество копируемых символов равно 5 String s2 = sb.ToString(6, 5); // s2 = "world" Console.WriteLine("s2 = ", s2);
6.9. Свойства Length , Capasity , MaxCapasity
В классе StringBuilder реализованы три целочисленные свойства, которые определяют характеристики строки:
- Length – текущее количество символов в строке;
- Capasity – количество символов, которые можно поместить в строку без дополнительного выделения памяти;
- MaxCapasity – максимальное содержимое строки, которая может быть выделена.
Пример.
// Свойства Length, Capasity, MaxCapasity StringBuilder sb = new StringBuilder("12345"); int len, capasity, maxCapasity; // Length - текущее количество символов в строке len = sb.Length; // length = 5 // Capasity - количество символов, которые могут быть помещены в строку без // дополнительного выделения памяти capasity = sb.Capacity; // capasity = 16 // MaxCapasity - максимальное содержимое строки, которая может быть выделена maxCapasity = sb.MaxCapacity; // maxCapasity = 2147483647
Связанные темы
String, StringBuilder и StringBuffer: понимаете ли вы разницу?
Все разработчики имеют дело со словами и фразами в некоторых частях кода. String — это тип данных, используемый в программировании для представления текста.
В Java есть три класса с именами String , StringBuilder и StringBuffer , где содержатся методы, написанные для операций над строками. Эти классы включены в пакет lang и импортируются в Java-код автоматически.
Здесь я расскажу подробнее об этих классах, а также о том, как и когда их использовать, чтобы облегчить себе работу со строками.
String
Строки в Java иммутабельны (не могут быть изменены). При изменении объекта String в Java каждый раз создается совершенно новый объект. В Java существует два способа объявить объект String, как это показано в примере ниже:
class StrEx1 public static void main(String[] args) String s1 = "This is a String"; // Объявлено с использованием строкового литерала
String s2 = new String("This is another String"); // Объявлено с использованием оператора new
>
>
Разница между этими двумя способами в том, что при использовании оператора new в памяти кучи каждый раз будет создаваться новый объект String. При использовании литерала объекта, если такой объект уже существует в куче, новый объект не появится, а ссылочная переменная будет указывать на существующий объект. При использовании строкового литерала объект String в Java сохраняется в так называемом пуле строк (String Pool). Он расположен внутри памяти кучи, что помогает Java Runtime сэкономить много места, даже если для создания объекта String при этом требуется больше времени. Так что, если вы хотите каждый раз создавать новый объект String, вам следует воспользоваться оператором new, а если вы хотите сберечь память кучи, тогда используйте строковый литерал.
При использовании оператора new, если в пуле строк такого объекта не существует, то сначала он будет создан в пуле строк, а затем уже и в памяти кучи. Ссылка на созданный строковый объект в таком случае всегда указывает на объект области кучи. Но если объект String уже существует в пуле строк, то объект будет создан только в памяти кучи. Такой вопрос нередко задают на собеседованиях по Java.
Класс String также предоставляет доступ ко многим полезным методам для различных операций над строками. Вот некоторые из этих методов: substring() , charat() , length() , equals() , concat() , replace() , trim() , split() , toUpperCase() и toLowerCase() . Эти методы можно применять как по отдельности, так и в сочетании с другими методами класса String, чтобы манипулировать строками так, как нам того захочется.
class StrEx2 public static void main(String args[]) String s1 = "Hello World";
String s2 = s1.substring(0,5).concat(" r2d2").toUpperCase();
System.out.println(s2); // Результат: HELLO R2D2
>
>
Здесь значение переменной s1 не изменяется.
StringBuilder
Класс StringBuilder представляет собой альтернативу классу String, поскольку создает мутабельный (изменяемый) набор символов. Класс StringBuilder, как и класс String, содержит набор методов для управления строковыми объектами.
class SbdEx1 public static void main(String args[]) StringBuilder sbd = new StringBuilder("Hello World");
String s = sbd.replace(5,11,"").append(" r2d2").toString();
System.out.println(sbd); // Результат: Hello r2d2
System.out.println(s.toUpperCase()); //Результат: HELLO R2D2
>
>
Классы StringBuilder и StringBuffer предоставляют важные методы, которых не предоставляет класс String, такие как insert() , delete() и reverse() . Если вы много раз совершаете какие-либо действия над строками в коде, вам следует использовать StringBuilder или StringBuffer, потому что они намного быстрее и потребляют меньше памяти, чем String. Например, если вы используете конкатенацию строк в цикле, то лучше применять StringBuilder.
class SbdEx2 public static void main(String args[]) StringBuilder sbd = new StringBuilder("0");
for (int i = 1; i < 100; i++) sbd.append(", "+i);
>
>
>
Класс StringBuilder не обеспечивает синхронизацию: экземпляры класса StringBuilder не могут совместно использоваться несколькими потоками. Для операций со строками в среде, не являющейся многопоточной, стоит использовать StringBuilder, потому что он быстрее, чем StringBuffer.
StringBuffer
Как и класс StringBuilder, класс StringBuffer также создает изменяемый строковый объект. И StringBuffer содержит те же методы, что и StringBuilder. Таким образом, разница между ними в том, что класс StringBuffer — потокобезопасный и синхронизированный: экземпляры класса StringBuffer могут совместно использоваться несколькими потоками. Для операций со строками в многопоточных средах стоит использовать StringBuffer.
class Test extends Thread <
StringBuffer sbr;
public Test() sbr = new StringBuffer();
>
public String hello() sbr.append("Hello World");
return(sbr.toString());
>
>
public class SbrEx <
public static void main(String args[]) Test thread1 = new Test();
thread1.start();
Test thread2 = new Test();
thread2.start();
System.out.println(thread1.hello());
System.out.println(thread2.hello());
>
>
Здесь несколько потоков обращаются к методу hello() , поэтому для обеспечения потокобезопасности необходимо применить StringBuffer.
Надеюсь, что вы все теперь разобрались со String, StringBuilder и StringBuffer. Спасибо, что прочитали!
- Java. Вложенные классы
- Портируем решатель судоку с Java на WebAssembly
- Основы программирования UDP-сокетов на Java
В чем разница между String, StringBuffer и StringBuilder?

Java
Автор Михаил Миронов На чтение 1 мин Обновлено 09.07.2023
Строки в Java реализованы в виде объектов класса String. Они финализированы и неизменяемы, вследствие этого при любых манипуляциях с ними всегда создается новая строка, что делает работу со строками весьма ресурсоёмким процессом. Если строки необходимо часто менять, то для этого есть StringBuffer и StringBuilder.
Естественным образом возникают вопросы:
- В чем разница между StringBuffer и StringBuilder?
- Что между ними общего?
- Когда лучше использовать StringBuffer , а когда StringBuilder?
Как уже было сказано, строки в Java неизменны и финализированы. В случае необходимости, манипуляции со строками в Java обеспечиваются двумя классами – StringBuffer и StringBuilder.
StringBuffer и StringBuilder реализуют изменяемые строки, а отличия между ними заключается в потокобезопасности и производительности.
Операции со StringBuffer, в отличие от StringBuilder, потокобезопасны и синхронизированы. Поэтому в случаях, когда несколько потоков должны работать с одной строкой, то необходимо использовать StringBuffer. Однако в однопоточных окружениях желательно использовать StringBuilder, поскольку преимущество StringBuilder перед StringBuffer заключается в производительности из-за отсутствия затрат для поддержки синхронизации.
- String – неизменяемая строка.
- StringBuffer — потокобезопасная изменяемая строка.
- StringBuilder – изменяемая строка с высокой производительностью, но без синхронизации.