4 июн. 2015 г.

Строки. Часть 3 – создание строк, классы StringBuilder и StringBuffer.

В JDK 5 в дополнение к существующим богатым возможностям обработки строк Java появился новый строковый класс. Этот новый класс называется StringBuilder. Он идентичен StringBuffer за исключением одного важного отличия: он не синхронизирован, что означает, что он не является безопасным в отношении потоков. Выгода от применения StringBuilder связана с более высокой производительностью. Однако в случае разработки многопоточных программ вы должны использовать StringBuffer, а не StringBuilder.

Класс StringBuilder

Объекты класса StringBuilder — это строки переменной длины. Только что созданный объект имеет буфер определенной емкости (capacity), по умолчанию достаточной для хранения 16 символов. Емкость можно задать в конструкторе объекта.

Как только буфер начинает переполняться, его емкость автоматически увеличивается, чтобы вместить новые символы.

В любое время емкость буфера можно увеличить, обратившись к методу

ensureCapacity(int minCapacity);

Этот метод изменит емкость, только если minCapacity будет больше длины хранящейся в объекте строки. Емкость будет увеличена по следующему правилу. Пусть емкость буфера равна N. Тогда новая емкость будет равна

Max(2 * N + 2, minCapacity)

Таким образом, емкость буфера нельзя увеличить менее чем вдвое.

Методом setLength(int newLength) можно установить любую длину строки. Если она окажется больше текущей длины, то дополнительные символы будут равны ' \u0000'. Если она будет меньше текущей длины, то строка окажется обрезанной, последние символы потеряются, точнее, будут заменены символом ' \u0000' . Емкость при этом не изменится.

Если число newLength окажется отрицательным, возникнет исключительная ситуация. Поэтому будьте осторожны, устанавливая новую длину строки.

Количество символов в строке можно узнать так же, как и для объекта класса String, методом length() , а емкость — методом capacity() .

Создать объект класса StringBuilder можно только конструкторами. То есть вы не можете создать строку класса StringBuilder операцией присваивания как мы это делали для класса String.

В классе StringBuilder определены четыре конструктора:

  • StringBuilder() — создает пустой объект с емкостью 16 символов;
  • StringBuilder(int capacity) — создает пустой объект заданной емкости capacity;
  • StringBuilder(String str) — создает объект емкостью str.length() + 16, содержащий строку str;
  • StringBuilder(CharSequence str) — создает объект, содержащий строку str.

Чтобы понять как создавать строки класса StringBuilder рассмотрим простой пример:

Str00012

Данная программа генерирует следующий вывод:

Str00013

Тут все очень просто, strBld1 и strBld2 это пустые строки, которые я не стал выводить на консоль, а вывел только их длину и емкость.

Строка strBld3 хоть и имеет длину 5 символов, но емкость объекта составляет 21 символ.

 

Совет: Начиная с этого момента я настоятельно рекомендую заглядывать в исходники JDK и смотреть код изучаемых классов, так как это весьма просветляет. Кроме того, я не смогу описать все методы всех классов, для этого есть сами классы и документация к ним, кою я вам и рекомендую регулярно читать.

Добавление подстроки – метод append()

Str00014

В классе StringBuilder есть более десяти методов append(), добавляющих подстроку в конец строки. Они не создают новый экземпляр строки, а возвращают ссылку на ту же самую, но измененную строку.
Основной метод append(String) присоединяет строку в конец данной строки. Если присоединяемая строка равна null, то добавляется строка "null".
Два аналогичных метода работают с параметром типа StringBuffer и CharSequence.
Шесть методов append(type) добавляют примитивные типы boolean, char, int, long, float, double, преобразованные в строку.
Два метода присоединяют к строке массив char и подмассив символов, преобразованные в строку: append(char[]) и append(char[], int, int).
Есть метод добавляющий к строке кодовую точку (code point) – appendCodePoint(int).

Метод, append(Object obj), добавляет просто объект. Перед этим объект obj преобразуется в строку своим методом toString().

Ну и как всегда немного практики:

Str00015

Собственно этот пример тоже очень простой и особо пояснять тут почти нечего.

Единственное что стоит отметить, так это использование собственного класса String0009, код которого я приведу чуть ниже.

Добавление даты, и данных класса String009 я сделал, чтобы продемонстрировать, что на объектах при их добавлении вызывается их метод toString().

И кстати сказать, добавление кодовой точки в строку при помощи appendCodePoint() куда проще чем то-же самое мы делали в классе String.

Код класса String009 очень простой и не замысловатый, хотя сейчас он может показаться вам не понятным, но потерпите немного, скоро мы доберемся и до классов.

Str00016

Два этих класса генерируют следующий вывод:

Str00017

 

 

 

Вставка подстроки – метод insert()

Str00018

Более десяти методов insert() предназначены для вставки строки, указанной вторым параметром метода, в данную строку. Место вставки задается первым параметром метода, индексом символа строки, перед которым будет сделана вставка. Он должен быть неотрицательным и меньше длины строки, иначе возникнет исключительная ситуация. Строка раздвигается, емкость буфера при необходимости увеличивается. Методы возвращают ссылку на ту же самую, но преобразованную строку.
Основной метод insert(int, String) вставляет строку в данную строку перед ее символом с индексом int. Если ссылка str == null, вставляется строка "null".
Метод sb.insert(sb.length(), "xxx") будет работать так же, как метод sb.append("xxx").

Шесть методов insert(int, type elem) вставляют примитивные типы boolean, char, int, long, float, double, преобразованные в строку.

Два метода вставляют массив char и подмассив char символов, преобразованные в строку.

Оставшиеся методы вставляют Object преобразованный в строку и объекты класса CharSequence.

Немножко практики:

Str00019

Данная программа генерирует следующий вывод:

Str00020

 

 

 

 

 

 

Удаление подстроки или символа – методы delete() и deleteChar()

Str00021

Метод delete(int beging, int end) удаляет из строки символы, начиная с индекса begin включительно до индекса end исключительно; если end больше длины строки, то до конца строки. Если begin отрицательно, больше длины строки или больше end, возникает исключительная ситуация. Если begin == end, удаление не происходит.

Метод deleteCharAt(int ind) удаляет символ с указанным индексом ind. Длина строки уменьшается на единицу. Если индекс ind отрицателен или больше длины строки, возникает исключительная ситуация. Допишем предыдущий пример, дабы не плодить классы без необходимости:

Str00022

Вывод программы:

Str00023

 

 

 

 

 

 

 

Переворот строки – метод reverse()

Метод reverse() меняет порядок расположения символов в строке на обратный.

Поиск подстроки в строке – методы indexOf() и lastIndexOf()

Str00024

Метод indexOf(String str) выполняет поиск первого вхождения str. Возвращает индекс позиции совпадения или -1 в случае неудачи.

Метод indexOf(String str, int startIndex) выполняет поиск первого вхождения str, начиная с startIndex. Возвращает индекс позиции совпадения или -1 в случае неудачи.

Метод lastIndexOf(String str) выполняет поиск последнего вхождения str. Возвращает индекс позиции совпадения или -1 в случае неудачи.

Метод lastIndexOf(String str, int startIndex) выполняет поиск последнего вхождения str, начиная с startIndex. Возвращает индекс позиции совпадения или -1 в случае неудачи.

Str00025

Вывод программы:

Str00026

В этой версии программы все тоже достаточно просто, поэтому, я надеюсь, она не требует особых объяснений.

Единственное что хочется еще раз напомнить, что строки в классах StringBuilder и StringBuffer изменяемые и при изменениях не создается нового объекта, а меняется существующий.

Ну вот мы и рассмотрели все методы класса StringBuilder. Далее рассмотрим методы класса StringBuffer. Класс StringBuffer имеет все те же методы, что и класс StringBuilder, но так же еще имеет несколько других, поэтому мы рассмотрим только их.

Класс StringBuffer

Получение подстроки из строки – метод substring()

Вы можете получить часть StringBuffer вызовом substring(). Этот метод возвращает строку класса String и имеет две следующие формы:

substring(int startIndex)
substring(int
startIndex, int endIndex)

Первая форма возвращает подстроку, которая начинается от startIndex и продолжается до конца объекта StringBuffer. Вторая форма возвращает подстроку от позиции startIndex до endIndex-1.

Например данный код:

StringBuffer strBfr1 = new StringBuffer("Подстрочка");
println("substring(int) = " + strBfr1.substring(3));
println("substring(int, int) = " + strBfr1.substring(0, 3));

выдаст следующий вывод:

substring(int) = строчка
substring(int, int) = Под

Далее есть несколько методов работы с кодовыми точками Unicode:

Str00027

Методы codePointAt() и  codePointBefore() возвращают значение типа int которое представляет кодовую точку Unicode или ее часть для указанного в параметре вызова индекса (символа). Метод codePointCount() возвращает число кодовых точек строки, заключенной между первым и вторым индексами.

Метод offsetByCodePoints(int start, int num) возвращает индекс символа в строке, которая находится на num точек кода позади начального индекса, указанного в start.

И остался еще метод trimToSize() который уменьшает размер символьного буфера объекта с тем, чтобы он соответствовал текущему содержимому.

Все вышеперечисленные методы работы с кодовыми точками и trimToSize() были добавлены в JDK 5.

Ну и для закрепления материала примерчик:

Str00028

Вывод у программы следующий:

Str00029

Первые три строки создают строку и затем выделают из нее подстроки.

Затем начинается самое интересно с кодовыми точками. Я подсветил желтым на что надо обратить особое внимание.

Хотя всего в строке 5 символов (ракета, три минуса и монорельс), длина же строки показывает 7 символов (char), это происходит потому, что два символа, ракета и монорельс состоят из двух char.

Далее смотрим сюда внимательно:

Str00030

И сравниваем коды монорельса и каждого из его двух char с тем что выводит программа.

Ну и на последок показана работа метода trimToSize().

Комментариев нет:

Отправить комментарий