Работа со строками в Java. Основные методы класса String.
Строка — это упорядоченная последовательность символов. В Java строка является основным носителем текстовой информации. Для работы со строками здесь используются следующие классы: String, StringBuilder, StringBuffer. В этом уроке речь пойдет о классе String, его на первых порах будет вполне достаточно.
В данном уроке рассматривается:
- Создание строк
- Конкатенация строк
- Наиболее употребительные методы класса String
- Конкатенация
- Определение количества символов в строке
- Извлечение символов из строки
- Извлечение подстроки из строки
- Разбиение строк
- Поиск в строке
- Модификация строк
- Сравнение строк
Создание строк
Строка в Java является объектом, поэтому ее можно создать, как и любой другой объект, при помощи оператора new.
Также строку можно создать при помощи литерала (фразы заключенной в кавычки) следующим образом.
Обе строки, независимо от способа создания являются объектами — экземплярами класса String.
Важный момент: создание объектов при помощи литерала возможно только в классе String. Объекты любого другого класса при помощи литерала создать нельзя.
Можно также создать массив строк. Например, так:
Конкатенация или слияние строк в Java
Для того, чтобы объединить несколько разных строк в одну, в Java можно использовать перегруженные (специально для объектов String) операторы «+» и «=+».
Еще один важный момент: операторы «+» и «=+», перегруженные для String, являются единственными перегруженными операторами в Java. Программист здесь не имеет возможности самостоятельно перегружать какие-либо операторы (как, например, в С++ и некоторых других языках).
Пример 1:
На консоль будет выведено «Мама мыла раму»
Пример 2:
Пример 3:
Наиболее употребительные методы класса String
String concat(String str) — производит ту же конкатенацию, что была описана выше, но использование этого метода из класса String положительно влияет на производительность и скорость программы. На небольших примерах это незаметно и не существенно, но в более серьезных приложениях стоит использовать этот метод. Результатом работы метода будет строка. Параметр, который нужно передавать в метод для конкатенации — тоже строка, о чем нам говорит значение в скобках (String str).
Перепишем пример 2, при помощи concat():
Определение количества символов в строке
Для того чтобы определить количество символов в строке, используется метод length.
int length() — возвращает длину строки. Длина равна количеству символов Unicode в строке.
Пример 4:
Если мы хотим работать со строкой, как с массивом символов, можем конвертировать строку в массив при помощи метода toCharArray.
char[] toCharArray() — преобразует строку в новый массив символов.
Пример 6: поменять в строке символы пробела на точки при помощи преобразования в массив символов (для этой задачи есть более простое решение, нежели преобразование в массив, но об этом чуть позже).
Примечание: в данном случае мы не сможем использовать метод charAt. При помощи этого метода мы бы смогли только найти пробелы в строке, но не поменять их.
Извлечение подстроки из строки
String substring(int beginIndex, int endIndex) или substring(int beginIndex) — возвращает новую строку, которая является подстрокой используемой строки. В параметрах метода нужно указать индекс строки, с которого начинается подстрока и индекс, которым заканчивается. Также возможно указывать только начальный индекс. В этом случае будет возвращена подстрока от начального индекса и до конца строки.
Пример 7.
Разбиение строк
Для разбиения строк на части используется метод String[] split(String regex), который разбивает строку на основании заданного регулярного выражения. О регулярных выражениях поговорим в одном из следующих уроков. Здесь покажем пример простого разбиения строки заданного одним символом.
Пример 8.
Поиск в строке
boolean contains(CharSequence s) — проверяет, содержит ли строка заданную последовательность символов и возвращает true или false.
Пример 9.
boolean endsWith(String suffix) — проверяет завершается ли строка определенными символами и возвращает true или false.
Пример 10.
boolean startsWith(String prefix) или startsWith(String prefix, int toffset) — проверяет, начинается ли строка с определенных символов. Во втором случае можно указать позицию с которой необходимо начать поиск префикса.
Пример 11.
int indexOf(int ch), indexOf(int ch, int fromIndex), indexOf(String str), indexOf(String str, int fromIndex) — метод indexOf применяется для поиска первого вхождения указанного символа в строке или первого вхождения указанной подстроки. Поиск также можно произвести с указанием позиции в строке от которой нужно начинать искать. Для поиска нужно указать соответствующие параметры. Метод возвращает число соответствующее индексу первого вхождения символа или подстроки. В случае отсутствия указанного символа или подстроки в строке, будет возвращена -1.
Пример 12
int lastIndexOf(int ch), lastIndexOf(int ch, int fromIndex), lastIndexOf(String str), lastIndexOf(String str, int fromIndex) — аналогично предыдущему случаю, только ищется последнее вхождение символа или подстроки в строке.
Модификация строк
Модификация строк не является модификацией как таковой. Дело в том, что объекты класса String после создания уже нельзя изменять. Но можно создать копию строки с изменениями. Именно это и делают следующие методы. toLowerCase() — преобразовать строку в нижний регистр; toUpperCase() — преобразовать строку в верхний регистр; trim() — отсечь на концах строки пустые символы;
Пример 13
String replace(char oldChar, char newChar), replace(CharSequence target, CharSequence replacement) — замена в строке одного символа или подстроки на другой символ или подстроку.
Вспомним пример 6, где нужно было поменять в строке символы пробела на точки и перепишем его с использованием replace:
Сравнение строк
boolean equals(Object anObject) — проверяет идентичность строк. Возвращает true только в том случае, если в строках представлена одинаковая последовательность символов одной величены.
Пример 14
int compareTo(String anotherString) — так же проверяет идентичность строк, однако, в отличии от метода equals возвращает:
нулевое значение, если строки равны, целое отрицательное число, если первая строка предшествует второй целое положительное число, если первая строка следует за второй Данный метод предназначен для упорядочивания строк. Он позволяет сравнить строки между собой и определить предшествующую строку. Для того, чтобы реализовать такое сравнение метод сравнивает числовые значения букв.
Рассмотрим пример с именами «Маша» и «Миша». При сравнении этих двух имен (пример 15), метод compareTo укажет, что имя «Маша» предшествует имени «Миша» (выдав отрицательное число) или наоборот, «Миша» следует за «Маша» (выдав положительное число). При упорядочивании имен по алфавиту мы бы упорядочили эти имена именно так. Метод в данном случае определяет, что числовое значение буквы «а» в «Маша» меньше, чем числовое значение «и» в Миша.
Пример 15
Однако, в случае, если мы напишем «маша» с маленькой буквы и попробуем сравнить с «Миша», то получим положительное число.
То есть в данном случае имя «Миша» предшествует имени «маша». Это происходит потому, что в таблице символов Юникода буквы верхнего регистра предшествуют нижнему.
Для сравнения строк без учета регистра символов используется функция int compareToIgnoreCase(String str)
Как мы видим, при сравнивании «маша» с «Миша» мы снова получаем отрицательное значение, то есть «маша» предшествует имени «Миша».
На этом закончим знакомство с методами класса String. Это далеко не все методы. Все методы класса String и их описание можно найти в официальной документации http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#method.summary
Вопросы для самопроверки
Если проверить на равенство строки “Тестовое задание” и “тестовое задание” методом equals, то они будут равны?
Сколькими способами описанными в лекции можно создать объект типа String?
Как мне получить последний символ строки?
Другие ответы очень полны, и вам обязательно стоит использовать их, если вы пытаетесь найти последний символ строки. Но если вы просто пытаетесь использовать условное выражение (например, это последний символ ‘g’), вы также можете сделать следующее:
Другие ответы содержат много ненужного текста и кода. Вот два способа получить последний символ строки:
символ
Строка
Использование символьного массива (остерегайтесь неприятных пустых аргументов String или null String!)
Другое решение использует StringBuilder (который обычно используется для выполнения строковых манипуляций, поскольку сам String неизменяем.
Еще один подход (больше для инструкции, чем для фактического использования) таков:
Здесь полная строка переворачивается, а затем часть, которую не следует переворачивать, заменяется подстрокой. 😉
Получить последние n символов из строки в Java
В этом посте будет обсуждаться, как получить последний n символов из строки в Java.
1. Использование Apache Commons Lang
Чтобы получить самое правое n символов строки, вы можете использовать right() метод, предложенный StringUtils класс из Apache Commons Lang. Преимущество использования этого метода в том, что он не выбрасывает StringIndexOutOfBoundsException или же NullPointerException когда n символы недоступны, или строка пуста.
Строки в Java
Как в большинстве других языков программирования, строка в Java – это последовательность символов (реализует интерфейс CharSequence). Но, в отличие от многих языков, которые реализуют строки как символьные массивы, в Java строки реализуются как объекты типа String .
Реализация строк в виде встроенных объектов обеспечивает полный комплект свойств, которые делают обработку строк очень удобной. Например, в Java существуют методы для сравнения двух строк, поиска подстроки, конкатенации (сцепления) двух строк и изменения регистра символов строки. Имеется несколько способов создания String-объектов , что облегчает их построение.
Несколько неожиданно, что после создания String-объекта символы, входящие в строку, нельзя изменять. Сначала это кажется серьезным ограничением. Однако это не так. Над этим объектом можно выполнять все типы строковых операций. Для того чтобы изменить версию существующей строки, нужно создать новый объект типа String , который содержит необходимую модификацию. Исходная строка остается неизменной. Этот подход используется, потому что фиксированные, неизменяемые строки можно реализовать более эффективно, чем изменяемые. Для тех случаев, когда желательна изменяемая строка, существует компаньон класса String с именем StringBuffer , чьи объекты содержат строки, которые могут изменяться после их создания.
Классы String и StringBuffer определены в пакете java.lang . Таким образом, они доступны всем программам автоматически. Оба объявлены как final, что означает, что ни один из этих классов не может иметь подклассов. При этом допускаются некоторые оптимизации, которые увеличивают эффективность строковых операций.
И последнее. Когда говорят, что строки в объектах типа String являются неизменяемыми, это означает, что содержимое String-объекта не может быть модифицировано после того, как он был создан. Однако переменную, объявленную как String-ссылка , можно в любое время изменить так, чтобы она указывала на другой String-объект .
Чтобы создать пустой объект типа String , необходимо поступить следующим образом:
String s = new String ();Данная операция создает экземпляр класса String , не содержащий символов (пустую строку).
Часто необходимо создавать строки с начальными значениями. Чтобы создать String-объект , инициализированный массивом символов, используйте следующий конструктор:
String(char chars[])
Например:Этот конструктор инициализирует (объектную) переменную s строкой "abc" .
При создании строки с использованием строкового литерала ( str1 и str2 в примере), переданная строка ищется в области памяти, называемой строковым пулом (string pool). Если такая строка найдена, то просто возвращается ссылка на нее. Если не найдена, то создается новый объект и также возвращается ссылка на него.
При создании строки с использованием оператора new будет фактически создано два объекта — строка будет и в строковом пуле и в куче. На картинке можно увидеть эти отличия более наглядно:
Можно также создать массив строк. Например, так:
Часто используемые методы класса String
Длина строки определяется количеством содержащихся в ней символов. Для получения этого значения вызовите метод length() . Пример:
Для соединения строк используются встроенные операции «+» и «+=».
Если нам требуется узнать, какой символ находится в строке на конкретной позиции, можем использовать метод charAt . Результатом работы метода будет символ типа char. Параметр, который передается в метод — целое число. Первый символ в строке, подобно массивам, имеет индекс 0.
Пример 5: определить последний символ в строке.
Если мы хотим работать со строкой, как с массивом символов, можем конвертировать строку в массив при помощи метода toCharArray .
Пример 6: поменять в строке символы пробела на точки при помощи преобразования в массив символов (для этой задачи есть более простое решение, нежели преобразование в массив, но об этом чуть позже).
Для извлечения подстроки из строки применяются методы substring(int beginIndex, int endIndex) или substring(int beginIndex) . Они возвращает новую строку, которая является подстрокой используемой строки. В параметрах метода нужно указать индекс строки, с которого начинается подстрока и индекс, которым заканчивается. Также возможно указывать только начальный индекс. В этом случае будет возвращена подстрока от начального индекса и до конца строки.
Для разбиения строк на части используется метод split(String regex) , который разбивает строку на основании заданного регулярного выражения.
Поиск в строке выполняет функция contains(CharSequence s) . Она проверяет, содержит ли строка заданную последовательность символов и возвращает true или false .
Функция endsWith(String suffix) проверяет завершается ли строка определенными символами. Назначение функции startsWith(String prefix) ясно, а вот ее версия startsWith(String prefix, int toffset) позволяет указать позицию с которой необходимо начать поиск префикса.
Функции toLowerCase() и toUpperCase() используются для преобразования строки в заданный регистр. Используются они, например когда вам надо выполнять команду, введенную пользователем и вам не важен регистр.
Функции replace(char oldChar, char newChar) и replace(CharSequence target, CharSequence replacement) выполняют замену в строке одного символа или подстроки на другой символ или подстроку.
Переписать рассмотренный выше фрагмент кода, заменяющий в строке пробелы на точки можно переписать с использованием этой функции так:
Пример обработки строк на Java
Для проверки равенства строк надо применять функцию equals , использовать для этого встроенный оператор == нельзя, так как он сравнит не значения строк, а объекты.
Если вам нужно узнать какая из двух строк «больше», например вы хотите упорядочить слова как в словаре — применяйте функцию int compareTo(String anotherString) . Обратите внимание, что она возвращает не boolean , а целое число, которое интерпретируется следующим образом:
- нулевое значение, если строки равны:4
- целое отрицательное число, если первая строка предшествует второй4
- целое положительное число, если первая строка следует за второй.
Рассмотрим пример с именами «Маша» и «Миша». При сравнении этих двух имен (пример 15), метод compareTo укажет, что имя «Маша» предшествует имени «Миша» (выдав отрицательное число) или наоборот, «Миша» следует за «Маша» (выдав положительное число). При упорядочивании имен по алфавиту мы бы упорядочили эти имена именно так. Метод в данном случае определяет, что числовое значение буквы «а» в «Маша» меньше, чем числовое значение «и» в Миша.
Для сравнения строк без учета регистра символов используется функция compareToIgnoreCase(String str) :
Строковый пул Java
Строковый пул в java — пример шаблона разработки ‘облегчения’ (flyweight). То есть по возможности не создавать копии завершенных объектов и не удалять их пока они используются.
Ниже приведены некоторые плюсы которые дает строковый пул:
- на одну и ту же строку могут ссылаться различные объекты
- кеширование строк
- уменьшение расхода памяти (результат первого)
- нет нужды в синхронизации на них в многопоточных приложениях
- при этом кешируется и хеш код строки, а значит повышается
быстродействие объектов типа HashMap;
При этом следует иметь в виду что строки в пуле живут дольше. А значит они доступны любому, имеющему доступ к дампу памяти программы. Поэтому секретные вещи как пароль лучше вообще хранить в виде символьного массива.
Явно сохранить строку в пуле можно методом intern . Интернирование иногда используется для оптимизации программы, чтобы вместо equal использовать ==.
Где-то читал, что имена классов также сохраняются в пуле. Но в андроиде на одном из устройств (Sony Erricson Xperia mini) это оказалось не так, пришлось их интернировать явно.
Преобразование данных в строки и обратно
В Java есть готовые решения по преобразования различных типов данных в строку и наоборот.
Преобразование простых типов в строку делается вызовом метода String.valueOf(arg).
Классы обертки простых типов имеют статический метод для создание объекта из строки SomeType.valueOf(String s). Например, Boolean.valueOf(String s) — возвращает true, если s не равно null и эквивалентно «true» без учета регистра символов.Для преобразования классов в строку переопределяется метод toString(). По умолчанию он возвращает имя класса.
Другой способ преобразования в строку — использование апи по форматированию строк по шаблону.
числа в строки
- String.valueOf(простой_тип) — создание строки из значения простого типа;
- Integer.toBinaryString(int i) — записать число в двоичной системе (как беззнаковое число);
- Integer.toHexString(int i) — записать число в шестнадцатиричной системе (как беззнаковое число);
- Integer.toOctalString(int i) — записать число в восьмеричной системе (как беззнаковое число);
Строки в числа
- Long.parseLong(String s) — возвращает число типа long, записанное в виде строки (целое знаковое десятичное число);
- Long.valueOf(String s) — аналогично предыдущему, но возвращает объект типа Long;
- Long.parseLong(String s, int radix) — возвращает число типа long записанное в указанной системе исчесления (с основанием до 36);
- Long.valueOf(String s, int radix) — аналогично предыдущему, но возвращает объект типа Long;
Аналогичные методы имеют классы Integer, Short, Float, Double.
дата, время и строки
Для преобразования даты и времени в строку и обратно используется класс SimpleDateFormat.
Форматирование строк по шаблону
Форматирование строки в стиле функции printf языка C поддерживается с помощью:
- Formatter — класс для форматирования строки;
- Formattable — интерфейс форматирования для объектов;
- System.out.printf(…) — форматированный вывод в системную консоль;
- String.format(…) — создание отформатированной строки;
Естественно форматирование адаптировано к языку java, т.е. поддерживаются такие java типы как byte, BigDecimal и Calendar. Более жесткая проверка типов. Возможность использования локализации.
структура шаблона
- argument_index — опциональный параметр указывающий номер аргумента, первый аргумент — «1$», второй — «2$», и т.д.;
- flags — опциональный параметр, набор символов модифицирующих формат вывода. Набор флагов зависит от conversionх;
- width — ширина, опциональный параметр задающий минимальное число символов, которое должно быть записано;
- precision — точность, опциональный параметр обычно ограничивающий число выводимых символов, более спец. значения зависит от conversion;
- conversion — преобразование, обязательный параметр символ задающий как аргумент должен быть отформатирован. Множество допустимых значений для конкретного аргумента зависит от типа аргумента;
преобразования
- ‘b’, ‘B’ — в логический тип, если аргумент null, выводится строка «false». Если аргумент типа boolean или Boolean, вызывается String.valueOf(). В остальных случаях результат «true»;
- ‘h’, ‘H’ — в шестнадатиричное целое число. Если аргумент null, выводится «null». В остальных случаях вызывается Integer.toHexString(arg.hashCode());
- ‘sv, ‘S’ — в строку. Если аргумент null, выводится «null». Если аргумент с интерфейсом Formattable, то вызывается его метод formatTo. В остальных случаях вызывается метод аргумента arg.toString();
- ‘c’, ‘C’ — в юникод символ;
- ‘d’ — в целое десятиченое число;
- ‘o’ — в целое восмиричное числов;
- ‘x’, ‘X’ — в целое шестнадцатириченое число;
- ‘e’, ‘E’ — вещественное число в научной нотации;
- ‘f’ — десятичное вещественое число;
- ‘g’, ‘G’ — вещественное число в научной нотации или в десятичном формате в зависимости от точности (параметр precision), значение округляется;
- ‘a’, ‘A’ — шестнадцатиричное вещественное число с точкое и экспонентой ;
- ‘t’, ‘T’ — префикс для преобразования временных значений, далее идут уточнияющие символы преобразования;
- ‘%’ — вывод сивола ‘%’ (‘\u0025’);
- ‘n’ — вывод разделителя строк используемого на текущей платформе;
интерфейс Formattable
Служит для форматирования объекта в строку. Если он не определен то для форматирования используется метод toString. Ниже приведен пример форматирования класса для использования в http get запросе.