Цикл статей «Учебник Java 8».
Следующая статья — «Java 8 автоупаковка и распаковка».
Предыдущая статья — «Java 8 числа».
В Java строки являются объектами класса java.lang.String, который является обычным классом но со специальной поддержкой компилятором. Этот класс представляет строку в виде набора символов UTF-16, где дополнительные символы представляются в виде суррогатных пар, другими словами один символ Юникода может состоять из двух char code unit. Индекс в строке адресует char code unit, а на символ. Дополнительные символы используют две позиции в строке.
char code unit — 16-битный символ char .
char code point — символ юникода. Может состоять из двух char -ов.
Такая путаница из char code unit и char code point произошла из-за того, что первоначально стандарт Юникода 1991 года предполагал 16-битные символы фиксированной длины, однако в последствии он был расширен в 1996 году для возможности представления символов, которым необходимо больше 16 бит.
Все строковые литералы в Java являются объектами класса String .
Примеры создания строк:
1 2 3 4 |
String greeting1 = "Hello world!"; char[] chardata = { 'h', 'e', 'l', 'l', 'o', '.' }; String greeting2 = new String(chardata); |
Для строковых литералов используются двойный кавычки, а для примитивного типа char — одинарные.
У класса String довольно много конструкторов. Можно, например, создать строку на основе массива байт:
1 2 |
java.nio.charset.Charset charset = java.nio.charset.Charset.forName("ISO-8859-1"); String str = new String(byteArray, charset); |
Или так:
1 2 3 4 5 |
try { String str = new String(byteArray, "ISO-8859-1"); } catch (java.io.UnsupportedEncodingException ex) { // Вывод информации об ошибке } |
В этих примерах "ISO-8859-1" — это имя кодировки.
Каждая реализация Java поддерживает следующие виды кодировок:
- US-ASCII
- ISO-8859-1
- UTF-8
- UTF-16BE
- UTF-16LE
- UTF-16
Дополнительно могут поддерживаться другие кодировки, например для Windows обязательно будет поддержка кодировки windows-1251.
Когда компилятор видит строковый литерал, например "Hello world!" , в коде, он создаёт объект класса java.lang.String.
Так как строковые литеры являются объектами, то у них можно вызывать методы:
1 |
System.out.println("Hi, Larry.".length()); // 10 |
В Java нет перегрузки операций, но класс строки имеет особую поддержку со стороны компилятора — строк можно соединять с помощью операции «+» (при этом используется java.lang.StringBuilder или java.lang.StringBuffer ):
1 2 |
String personName = "Vasya"; System.out.println(personName + " goes" + " to school."); // Vasya goes to school. |
Конкатенации строковых литералов вида " goes" + " to school." компилятор вычисляет на этапе компиляции, поэтому во время выполнения не будет происходить лишних операций. Можно с помощью «+» разделять строковые константы на несколько строк, компилятор уберёт лишние операции сам и превратит всё в одну строковую литералу:
1 2 3 |
String str1 = "Vasya goes to school." + " Petya does the same thing too." + " Turtle power!!!"; |
Каждый объект в Java может участвовать в операции конкатенации (соединения) строк, в этом случае используется метод toString() , (если ссылка на объект равна null, то используется строка "null" ):
1 2 3 4 5 6 7 8 9 10 11 12 13 |
Object obj1 = new Object() { @Override public String toString() { return "obj1toString()"; } }; Integer integer1 = 23; java.math.BigDecimal bigDecimal1 = new java.math.BigDecimal("3.45"); Object obj2 = null; System.out.println("obj1: " + obj1 + "; integer1: " + integer1 + "; bigDecimal1: " + bigDecimal1 + "; obj2: " + obj2); |
Выведет в консоль:
1 |
obj1: obj1toString(); integer1: 23; bigDecimal1: 3.45; obj2: null |
Класс String НЕ имеет специальной поддержки для == , поэтому сравнивать строки нужно либо через метод equals() , либо equalsIgnoreCase() , либо compareTo() , либо compareToIgnoreCase() .
В Java используется пул строковых литералов. Одинаковые строковые литералы всегда ссылаются на один и тот же экземпляр класса String :
1 2 3 4 5 |
String vasya = "Vasya", ya = "ya"; System.out.println(vasya == "Vasya"); // 1 System.out.println(vasya == ("Vas" + ya)); // 2 System.out.println(vasya == ("Vas" + "ya")); // 3 System.out.println(vasya == ("Vas" + ya).intern()); // 4 |
Этот код выведет:
1 2 3 4 |
true false true true |
Объяснение:
- Одинаковые строковые литералы всегда ссылаются на один и тот же экземпляр класса String.
- Экземпляры классы String, вычисленные во время выполнения, создаются заново, автоматически в пуле не участвуют и потому различны.
- Строковые литералы в константных выражениях вычисляются на этапе компиляции и затем расцениваются как обычные литералы.
- С помощью метода intern() можно добавить строку в пул либо получить ссылку на такую строку из пула.
Многие методы строки принимают в качестве параметра или возвращают в качестве результата индекс. Индексация начинается с нуля. Первый char (имеется в виду char code unit, а не символ, разумеется) в строке имеет индекс 0, а последний имеет индекс length() — 1. Если переданный в параметр индекс выходит за пределы строки, то методы генерируют исключение java.lang.IndexOutOfBoundsException.
Некоторые методы принимают в качестве параметров начальный индекс и конечный индекс. В этом случае начальный индекс включается в отрезок, а конечный индекс исключается, так что длина отрезка получается равной конечный индекс минус начальный индекс, как на картинке.
Подобная индексация является стандартом в Java. Всегда когда указывается отрезок в массиве, строке, списке или ещё-где-то, начальный индекс включается в отрезок, а конечный исключается.
Методы класса java.lang.String
1 |
public char charAt(int index) |
Возвращает
char (Unicode code unit) по указанному индексу.
1 |
public int codePointAt(int index) |
Возвращает символ (Unicode code point) по указанному индексу. Индекс указывается для
char-ов.
1 |
public int compareTo(String anotherString) |
Лексикографическое сравнение строк. Возвращает -1, если текущая строка лексикографически меньше
anotherString, 0 — строки лексикографически равны, 1 — текущая строка лексикографически больше. Метод полезен для сортировки строк.
1 |
public int compareToIgnoreCase(String str) |
Лексикографическое сравнение, игнорирующее разницу в регистрах букв.
1 |
public String concat(String str) |
Если длина строки
str равна 0, то возвращает
this, иначе возвращает строку, являющуюся конкатенацией (объединением) текущей строки и
str.
1 |
public boolean contains(CharSequence s) |
Возвращает
true, если текущая строка содержит последовательность символов
s. Класс
java.lang.String реализует интерфейс
java.lang.CharSequence, так что в качестве параметра можно передавать экземпляр класса
String.
1 |
public boolean endsWith(String suffix) |
Возвращает
true, если текущая строка заканчивается на
suffix или равна ему. Если
suffix является пустой строкой, то возвращает
true.
1 |
public byte[] getBytes(Charset charset) |
1 2 |
public byte[] getBytes(String charsetName) throws UnsupportedEncodingException |
Возвращают массив байт, содержащий строку в указанной кодировке.
1 |
public int indexOf(int ch) |
1 2 |
public int indexOf(int ch, int fromIndex) |
Возвращает индекс первого вхождения символа ch, начиная с fromIndex. Если символ не найден, то возвращает -1.
public int indexOf(String str)
1 2 |
public int indexOf(String str, int fromIndex) |
Возвращает индекс первого вхождения подстроки в строке, начиная с
fromIndex. Если подстрока не найдена, то возвращает -1.
1 2 3 |
public static String format(Locale l, String format, Object... args) |
1 2 |
public static String format(String format, Object... args) |
Форматированный вывод. Более подробно будет рассмотрен в статье про форматирование.
1 |
public String intern() |
Магический метод. В Java существует пул строк. Этот метод проверяет наличие строки в пуле, если в пуле есть такая строка, то метод возвращает ссылку на неё. Если в пуле нет такой строки, то строка добавляется в пул, и возвращается ссылка на неё. Все строковые литералы и константы автоматически включаются в пул. Примеры:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
boolean b1 = "Vasya" == "Vasya"; // true, так как в пуле будет одно значение Vasya. String str1 = "Vasya"; String substr1 = "Vas"; String str2 = substr1 + "ya"; // Но если сделать "Vas" + "ya", то будет // ссылаться туда же, // так как подобные конкатенации строковых // констант компилятор автоматически убирает boolean b2 = str1 == str2; // false String str3 = "Vasya"; boolean b3 = str1 == str3; // true str2 = str2.intern(); boolean b4 = str1 == str2; // true; |
1 2 |
public static String join(CharSequence delimiter, CharSequence... elements) |
Объединяет несколько
CharSequence в одну строку, используя в качестве разделителя
delimiter.
1 |
public int length() |
Возвращает длину строки в
char -ах (Unicode code units). Количество символов в строке (Unicode code points) может отличаться от этого значения.
1 |
public boolean isEmpty() |
Возвращает
true , если
length() == 0.
1 2 |
public String replace(char oldChar, char newChar) |
Возвращает строку, в которой все
oldChar заменены на
newChar. Если
oldChar в строке нет, то возвращается исходная строка.
1 2 |
public String replaceAll(String regex, String replacement) |
Возвращает строку, в которой все вхождения подстрок согласно регулярному выражению заменены на replacement.
1 2 |
public String replace(CharSequence target, CharSequence replacement) |
Возвращает строку, в которой все вхождения последовательности символов
target заменены на
replacement.
1 |
public String substring(int beginIndex) |
1 2 |
public String substring(int beginIndex, int endIndex) |
Возвращает подстроку, начинающуюся с
beginIndex (включительно) до
endIndex (исключительно) или конца строки.
1 |
public String[] split(String regex) |
Разбивает строку на массив строк по регулярному выражению. Пустые конечные строки не включаются в результирующий массив.
1 |
public boolean startsWith(String prefix) |
Возвращает
true , если строка начинается с
prefix либо равна ему. Если
prefix является пустой строкой, то возвращается
true.
1 |
public String toLowerCase() |
1 |
public String toLowerCase(Locale locale) |
Возвращает строку, где все символы приведены в нижний регистр относительно текущей локали или указанной.
1 |
public String toUpperCase() |
1 |
public String toUpperCase(Locale locale) |
Возвращает строку, где все символы приведены в верхний регистр относительно текущей локали или указанной.
1 |
public String trim() |
Возвращает строку, в которой убраны пробелы в начале и в конце строки. Если строка начинается и заканчивается на непробельные символы (больше
'\u0020'), то возвращается ссылка на
this.
1 |
public static String valueOf(boolean b) |
1 |
public static String valueOf(char c) |
1 |
public static String valueOf(int i) |
1 |
public static String valueOf(long l) |
1 |
public static String valueOf(float f) |
1 |
public static String valueOf(double d) |
1 |
public static String valueOf(Object obj) |
Возвращает строковое представление объекта. В случае с Object результатом является obj.toString(), если obj != null и "null" в противном случае.
и другие методы.
java.lang.StringBuilder
В отличие от String класс StringBuilder позволяет менять содержимое своих экземпляров. В большинстве случаев нужно использовать String, использование же StringBuilder целесообразно в случаях, когда вам нужно соединить большое количество строковых переменных, например перебирая элементы массива или коллекции в цикле.
Так же как и у String у StringBuilder есть метод length(), позволяющий узнать его длину в char-ах.
В отличие от String у StringBuilder кроме длины есть ещё вместимость/ёмкость (capacity). Вместительность можно узнать с помощью метода capacity(), она всегда больше или равна длине.
Конструктор | Описание |
---|---|
StringBuilder() |
Создаёт пустой StringBuilder вместительностью 16 (16 пустых элементов). |
StringBuilder(CharSequence cs) |
Создаёт StringBuilder , содержащий символы из последовательности и 16 дополнительных пустых элементов. |
StringBuilder(int initCapacity) |
Создаёт пустой StringBuilder с начальной вместительностью в initCapacity элементов. |
StringBuilder(String s) |
Создаёт StringBuilder , который содержит указанную строку и 16 дополнительных пустых элементов. |
StringBuilder содержит пару дополнительных методов, связанных с длиной, которых нет в String:
Метод | Описание |
---|---|
void setLength(int newLength) |
Устанавливает длину последовательности символов. Если newLength меньше length(), то последние символы обрезаются. Если newLength больше length(), то в конец последовательности добавляются нулевые символы. |
void ensureCapacity(int minCapacity) |
Обеспечивает, что вместительность будет как минимум равной minCapacity. |
Некоторые методы могут увеличить длину последовательности символов в StringBuilder. Если после выполнения подобного метода длина результирующей последовательности окажется больше вместительности, то вместительность автоматически увеличится.
Метод | Описание |
---|---|
StringBuilder append(boolean b) |
Добавляет аргумент, преобразованный в строку, в конец StringBuilder-а. |
StringBuilder delete(int start, int end) |
Первый метод удаляет подпоследовательность с start до end-1 включительно. Второй метод удаляет символ по индексу. |
StringBuilder insert(int offset, boolean b) |
Вставляет второй аргумент, конвертированный в строку, в позицию index. |
StringBuilder replace(int start, int end, String s) |
Заменяет указанный символ/ы. |
StringBuilder reverse() |
Меняет порядок символов в StringBuilder на обратный. Первый символ становится последним и так далее. |
String toString() |
Возвращает строку, содержащую последовательность символов из StringBuilder. |
Пример использования StringBuilder:
1 2 3 4 5 6 |
String andStr = " and Petya"; StringBuilder stringBuilder = new StringBuilder(); stringBuilder.append("Vasya"); stringBuilder.append(andStr); stringBuilder.append(" go to school."); System.out.println(stringBuilder); |
Цикл статей «Учебник Java 8».
Следующая статья — «Java 8 автоупаковка и распаковка».
Предыдущая статья — «Java 8 числа».
= Задача
Читаем строки из текстового файла «onegin.txt» (призовем на помощь классика). Файл имеет размер 297463 байта, utf-8, 27195 слов. Сложим все слова файла в одну строку с использованием всех трех классов и сравним производительность.
= = Цифры
(юзаются разные JVM и ОС)
= Linux
Класс Open JDK 1.6.0_18 HotSpot 1.6.0_20 JRockit 4.0.1
String 27390ms 26850ms 26940ms
StringBuffer 35.55ms 34.87ms 15.41ms
StringBuilder 33.01ms 31.78ms 12.82ms
= Windows XP
Класс HotSpot 1.6.0_20 JRockit 4.0.1
String 55260ms 45330ms
StringBuffer 19.38ms 14.50ms
StringBuilder 16.83ms 12.76ms
— —
То есть, при больших файлах, разница в производительности между String и StringBuffer/StringBuilder может быть в несколько сотен раз.
= Источник
https://habrahabr.ru/post/102468/