StringBuffer и StringBuilder
1. Отличие между String, StringBuilder, StringBuffer
- Классы StringBuffer и StringBuilder в Java используются, когда возникает необходимость сделать много изменений в строке символов.
- В отличие от String , объекты типа StringBuffer и StringBuilder могут быть изменены снова и снова.
- В Java StringBuilder был введен начиная с Java 5.
- Основное различие между StringBuffer и StringBuilder в Java является то, что методы StringBuilder не являются безопасными для потоков (несинхронизированные).
- Рекомендуется использовать StringBuilder всякий раз, когда это возможно, потому что он быстрее, чем StringBuffer в Java.
- Однако, если необходима безопасность потоков, наилучшим вариантом являются объекты StringBuffer .
2. Конструкторы StringBuilder
- StringBuilder() — объект StringBuilder можно создать без параметров, при этом в нем будет зарезервировано место для размещения 16 символов.
- StringBuilder(int size) — вы также можете передать конструктору целое число, для того чтобы явно задать требуемый размер буфера.
- StringBuilder(String str) — вы можете передать конструктору строку, при этом она будет скопирована в объект и дополнительно к этому в нем будет зарезервировано место еще для 16 символов.
- StringBuilder(CharSequence chars)
В следующем примере создадим объект класса StringBuilder , и выведем на консоль его размер методом length() . Метод capacity() возвращает размер буфера:
public class StringBuilderDemo1 < public static void main(String[] args) < StringBuilder stringBuilder = new StringBuilder("Hello"); System.out.println("string = " + stringBuilder); System.out.println("length = " + stringBuilder.length()); System.out.println("capacity header3">3. Методы charAt(), setCharAt() Метод charAt() возвращает символ в указанной позиции. А setCharAt() изменяет символ в указанной позиции:
public class SetCharAtDemo < public static void main(String[] args) < StringBuilder sb = new StringBuilder("Hello"); System.out.println(sb); System.out.println("charAt(1) header4">4. Метод append() Метод append() присоединяет подстроку к строке:
public class AppendDemo < public static void main(String[] args) < int a = 42; StringBuilder sb = new StringBuilder(40); String s = sb.append("a = ").append(a).append("!").toString(); System.out.println(s); >>
5. Метод insert()
Метод insert() вставляет подстроку в указанную позицию:
public class InsertDemo < public static void main(String[] args) < StringBuilder sb = new StringBuilder("I Java!"); sb.insert(2, "like "); System.out.println(sb); >>
6. Метод reverse()
Используется для инвертирования строки:
public class ReverseDemo < public static void main(String[] args) < StringBuilder s = new StringBuilder("abcdef"); System.out.println(s); s.reverse(); System.out.println(s); >>
7. Методы delete() и deleteCharAt()
Метод delete() удаляет подстроку, используя указанные позиции.
Метод deleteCharAt() удаляет символ с указанной позиции:
public class DeleteDemo < public static void main(String[] args) < StringBuilder sb = new StringBuilder("This is a test."); sb.delete(4, 7); System.out.println("После delete: " + sb); sb.deleteCharAt(0); System.out.println("После deleteCharAt: " + sb); >>
8. Метод replace()
Заменяет подстроку в указанной позиции другой:
public class ReplaceDemo < public static void main(String[] args) < StringBuilder stringBuilder = new StringBuilder("Этo простой тест."); stringBuilder.replace(4, 11, "был"); System.out.println("После замены: " + stringBuilder); >>
9. Методы equals() и hashCode()
Классы StringBuilder и StringBuffer не переопределяют методы equals() и hashCode() . Они используют реализацию класса Object :
public class StringBuilderEquals < public static void main(String[] args) < StringBuilder stringBuilder1 = new StringBuilder("Hello"); StringBuilder stringBuilder2 = new StringBuilder("Hello"); System.out.println(stringBuilder1.equals(stringBuilder2)); System.out.println(stringBuilder1 == stringBuilder2); >>
Как работает stringbuilder java
Объекты String являются неизменяемыми, поэтому все операции, которые изменяют строки, фактически приводят к созданию новой строки, что сказывается на производительности приложения. Для решения этой проблемы, чтобы работа со строками проходила с меньшими издержками в Java были добавлены классы StringBuffer и StringBuilder . По сути они напоминает расширяемую строку, которую можно изменять без ущерба для производительности.
Эти классы похожи, практически двойники, они имеют одинаковые конструкторы, одни и те же методы, которые одинаково используются. Единственное их различие состоит в том, что класс StringBuffer синхронизированный и потокобезопасный. То есть класс StringBuffer удобнее использовать в многопоточных приложениях, где объект данного класса может меняться в различных потоках. Если же речь о многопоточных приложениях не идет, то лучше использовать класс StringBuilder, который не потокобезопасный , но при этом работает быстрее, чем StringBuffer в однопоточных приложениях.
StringBuffer определяет четыре конструктора:
StringBuffer() StringBuffer(int capacity) StringBuffer(String str) StringBuffer(CharSequence chars)
Аналогичные конструкторы определяет StringBuilder:
StringBuilder() StringBuilder(int capacity) StringBuilder(String str) StringBuilder(CharSequence chars)
Рассмотрим работу этих классов на примере функциональности StringBuffer.
При всех операциях со строками StringBuffer / StringBuilder перераспределяет выделенную память. И чтобы избежать слишком частого перераспределения памяти, StringBuffer/StringBuilder заранее резервирует некоторую область памяти, которая может использоваться. Конструктор без параметров резервирует в памяти место для 16 символов. Если мы хотим, чтобы количество символов было иным, то мы можем применить второй конструктор, который в качестве параметра принимает количество символов.
Третий и четвертый конструкторы обоих классов принимают строку и набор символов, при этом резервируя память для дополнительных 16 символов.
С помощью метода capacity() мы можем получить количество символов, для которых зарезервирована память. А с помощью метода ensureCapacity() изменить минимальную емкость буфера символов:
String str = "Java"; StringBuffer strBuffer = new StringBuffer(str); System.out.println("Емкость: " + strBuffer.capacity()); // 20 strBuffer.ensureCapacity(32); System.out.println("Емкость: " + strBuffer.capacity()); // 42 System.out.println("Длина: " + strBuffer.length()); // 4
Так как в самом начале StringBuffer инициализируется строкой "Java", то его емкость составляет 4 + 16 = 20 символов. Затем мы увеличиваем емкость буфера с помощью вызова strBuffer.ensureCapacity(32) повышаем минимальную емкость буфера до 32 символов. Однако финальная емкость может отличаться в большую сторону. Так, в данном случае я получаю емкость не 32 и не 32 + 4 = 36, а 42 символа. Дело в том, что в целях повышения эффективности Java может дополнительно выделять память.
Но в любом случае вне зависимости от емкости длина строки, которую можно получить с помощью метода length() , в StringBuffer остается прежней - 4 символа (так как в "Java" 4 символа).
Чтобы получить строку, которая хранится в StringBuffer, мы можем использовать стандартный метод toString() :
String str = "Java"; StringBuffer strBuffer = new StringBuffer(str); System.out.println(strBuffer.toString()); // Java
По всем своим операциям StringBuffer и StringBuilder напоминают класс String.
Получение и установка символов
Метод charAt() получает, а метод setCharAt() устанавливает символ по определенному индексу:
StringBuffer strBuffer = new StringBuffer("Java"); char c = strBuffer.charAt(0); // J System.out.println(c); strBuffer.setCharAt(0, 'c'); System.out.println(strBuffer.toString()); // cava
Метод getChars() получает набор символов между определенными индексами:
StringBuffer strBuffer = new StringBuffer("world"); int startIndex = 1; int endIndex = 4; char[] buffer = new char[endIndex-startIndex]; strBuffer.getChars(startIndex, endIndex, buffer, 0); System.out.println(buffer); // orl
Добавление в строку
Метод append() добавляет подстроку в конец StringBuffer:
StringBuffer strBuffer = new StringBuffer("hello"); strBuffer.append(" world"); System.out.println(strBuffer.toString()); // hello world
Метод insert() добавляет строку или символ по определенному индексу в StringBuffer:
StringBuffer strBuffer = new StringBuffer("word"); strBuffer.insert(3, 'l'); System.out.println(strBuffer.toString()); //world strBuffer.insert(0, "s"); System.out.println(strBuffer.toString()); //sworld
Удаление символов
Метод delete() удаляет все символы с определенного индекса о определенной позиции, а метод deleteCharAt() удаляет один символ по определенному индексу:
StringBuffer strBuffer = new StringBuffer("assembler"); strBuffer.delete(0,2); System.out.println(strBuffer.toString()); //sembler strBuffer.deleteCharAt(6); System.out.println(strBuffer.toString()); //semble
Обрезка строки
Метод substring() обрезает строку с определенного индекса до конца, либо до определенного индекса:
StringBuffer strBuffer = new StringBuffer("hello java!"); String str1 = strBuffer.substring(6); // обрезка строки с 6 символа до конца System.out.println(str1); //java! String str2 = strBuffer.substring(3, 9); // обрезка строки с 3 по 9 символ System.out.println(str2); //lo jav
Изменение длины
Для изменения длины StringBuffer (не емкости буфера символов) применяется метод setLength() . Если StringBuffer увеличивается, то его строка просто дополняется в конце пустыми символами, если уменьшается - то строка по сути обрезается:
StringBuffer strBuffer = new StringBuffer("hello"); strBuffer.setLength(10); System.out.println(strBuffer.toString()); //"hello " strBuffer.setLength(4); System.out.println(strBuffer.toString()); //"hell"
Замена в строке
Для замены подстроки между определенными позициями в StringBuffer на другую подстроку применяется метод replace() :
StringBuffer strBuffer = new StringBuffer("hello world!"); strBuffer.replace(6,11,"java"); System.out.println(strBuffer.toString()); //hello java!
Первый параметр метода replace указывает, с какой позиции надо начать замену, второй параметр - до какой позиции, а третий параметр указывает на подстроку замены.
Обратный порядок в строке
Метод reverse() меняет порядок в StringBuffer на обратный:
StringBuffer strBuffer = new StringBuffer("assembler"); strBuffer.reverse(); System.out.println(strBuffer.toString()); //relbmessa
Классы StringBuffer и StringBuilder
Класс String представляет собой неизменяемые последовательности символов постоянной длины и частое использование объектов класса занимают много места в памяти. Класс StringBuffer представляет расширяемые и доступные для изменений последовательности символов, позволяя вставлять символы и подстроки в существующую строку и в любом месте. Данный класс гораздо экономичнее в плане потребления памяти и настоятельно рекомендуется к использованию.
Существует четыре конструктора класса:
- StringBuffer() - резервирует место под 16 символов без перераспределения памяти
- StringBuffer(int capacity) - явно устанавливает размер буфера
- StringBuffer(String string) - устанавливает начальное содержимое и резервирует 16 символов без повторого резервирования
- StringBuffer(CharSequence cs) - создаёт объект, содержащий последовательность символов и резервирует место ещё под 16 символов
Методы класса StringBuffer
length()
Метод позволяет получить текущую длину объекта.
StringBuffer sb = new StringBuffer("Котэ"); mInfoTextView.setText("Длина: " + sb.length());
capacity()
Метод позволяет получить текущий объём выделенной памяти.
StringBuffer sb = new StringBuffer("Котэ"); mInfoTextView.setText("Объём памяти: " + sb.capacity()); // вернёт 20
Обратите внимание, что хотя слово состоит из четырёх символов, в памяти выделено запасное пространство для дополнительных 16 символов. Для такой простейшей операции выигрыша нет, но в сложных примерах, когда приходится на лету соединять множество строк, производительность резко возрастает.
ensureCapacity()
Можно предварительно выделить место для определённого количества символов, если собираетесь добавлять большое количество маленьких строк.
setLength(int length)
Устанавливает длину строки. Значение должно быть неотрицательным.
charAt(int index) и setCharAt(int index, char ch)
Можно извлечь значение отдельного символа с помощью метода charAt() и установить новое значение символа с помощью метода setCharAt(), указав индекс символа и его значение.
StringBuffer sb = new StringBuffer("Кит"); sb.setCharAt(1, 'o'); mInfoTextView.setText(sb.toString());
getChars()
Позволяет скопировать подстроку из объекта класса StringBuffer в массив. Необходимо позаботиться, чтобы массив был достаточного размера для приёма нужного количества символов указанной подстроки.
append()
Метод соединяет представление любого другого типа данных. Есть несколько перегруженных версий.
StringBuffer append(String string) StringBuffer append(int number) StringBuffer append(Object object)
Строковое представление каждого параметра за кулисами получают через метод String.valueOf() и затем полученные строки склеиваются в итоговую строку.
String str1 = "У кота "; String str2 = " лапы"; int paws = 4; StringBuffer sb = new StringBuffer(20); sb.append(str1).append(paws).append(str2); mInfoTextView.setText(sb.toString());
insert()
Вставляет одну строку в другую. Также можно вставлять значения других типов, которые будут автоматически преобразованы в строки. Вам надо указать индекс позиции, куда будет вставляться строка.
StringBuffer sb = new StringBuffer("Я Котов"); sb.insert(2, "Люблю "); mInfoTextView.setText(sb.toString());
reverse()
Позволяет изменить порядок символов на обратный.
StringBuffer sb = new StringBuffer("МОКНЕТ ОКСАНА С КОТЕНКОМ"); sb.reverse(); mInfoTextView.setText(sb.toString());
У меня получилось практически то же самое, может метод глючит?
delete() и deleteCharAt()
Метод delete() удаляет последовательность символов, вам надо задать индекс первого символа, который надо удалить, а также индекс символа, следующего за последним из удаляемых. Метод deleteCharAt() удаляет один символ из указанной позиции.
replace()
Позволяет заменить один набор символов на другой. Нужно указать начальный и конечный индекс и строку замены.
substring()
Позволяет получить часть содержимого. Есть две формы метода. В первом случае нужно указать индекс начала позиции, с которой нужно получить подстроку. Во втором варианте указывается начальный индекс и конечный индекс, если нужно получить текст из середины строки.
Есть и другие методы
StringBuilder
Класс StringBuilder идентичен классу StringBuffer и обладает большей производительностью. Однако он не синхронизирован, поэтому его не нужно использовать в тех случаях, когда к изменяемой строке обращаются несколько потоков.
Создадим новый объект.
StringBuilder builder = new StringBuilder();
Добавляем новый фрагмент в существующую строку:
builder.append(ch); // можно добавить один символ builder.append(sometext); // а можно добавить готовую строку String completedString = builder.toString(); // результирующая строка
Соединять строки можно цепочкой.
new StringBuilder().append(s1).append(s2).append(s3).toString();
Данный код работает чуть быстрее, чем вызов append() по отдельности. Но это будет заметно при очень больших объёмах.
StringBuilder — Java: Массивы
Генерация строк в циклах — задача, часто возникающая на практике. Типичный пример — метод, помогающий генерировать HTML-списки. Он принимает на вход массив элементов и возвращает HTML-список из них:
Как можно решить эту задачу "в лоб":
- Создать переменную result и записать в нее
.
- Пройтись циклом по элементам коллекции и дописать в результирующую строку очередной элемент
- .
- Добавить в конце
и вернуть result из функции.
Такой способ вполне рабочий, но для большинства языков программирования максимально неэффективный. Дело в том, что конкатенация порождает новую строчку вместо старой, — и подобная ситуация повторяется на каждой итерации. Причем строка становится все больше и больше. Копирование строк приводит к серьезному расходу памяти и влияет на производительность.
Правильный способ для динамической сборки строк в Java - использование класса StringBuilder . Он позволяет собирать строку по кусочкам без лишнего копирования. Перепишем наш пример:
Открыть доступ
Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно
- 130 курсов, 2000+ часов теории
- 1000 практических заданий в браузере
- 360 000 студентов
Наши выпускники работают в компаниях: