Длина строки в java. метод length()
Содержание:
Введение в строки. Класс String
Последнее обновление: 31.10.2018
Строка представляет собой последовательность символов. Для работы со строками в Java определен класс String, который предоставляет ряд методов для манипуляции строками.
Физически объект String представляет собой ссылку на область в памяти, в которой размещены символы.
Для создания новой строки мы можем использовать один из конструкторов класса String, либо напрямую присвоить строку в двойных кавычках:
public static void main(String[] args) { String str1 = "Java"; String str2 = new String(); // пустая строка String str3 = new String(new char[] {'h', 'e', 'l', 'l', 'o'}); String str4 = new String(new char[]{'w', 'e', 'l', 'c', 'o', 'm', 'e'}, 3, 4);//3 -начальный индекс, 4 -кол-во символов System.out.println(str1); // Java System.out.println(str2); // System.out.println(str3); // hello System.out.println(str4); // come }
При работе со строками важно понимать, что объект String является неизменяемым (immutable). То есть при любых операциях
над строкой, которые изменяют эту строку, фактически будет создаваться новая строка
Поскольку строка рассматривается как набор символов, то мы можем применить метод length() для нахождения длины строки или длины набора символов:
String str1 = "Java"; System.out.println(str1.length()); // 4
А с помощью метода toCharArray() можно обратно преобразовать строку в массив символов:
String str1 = new String(new char[] {'h', 'e', 'l', 'l', 'o'}); char[] helloArray = str1.toCharArray();
Строка может быть пустой. Для этого ей можно присвоить пустые кавычки или удалить из стоки все символы:
String s = ""; // строка не указывает на объект if(s.length() == 0) System.out.println("String is empty");
В этом случае длина строки, возвращаемая методом length(), равна 0.
Класс String имеет специальный метод, который позволяет проверить строку на пустоту — isEmpty(). Если строка пуста, он возвращает true:
String s = ""; // строка не указывает на объект if(s.length() == 0) System.out.println("String is empty");
Переменная String может не указывать на какой-либо объект и иметь значение null:
String s = null; // строка не указывает на объект if(s == null) System.out.println("String is null");
Значение null не эквивалентно пустой строке. Например, в следующем случае мы столкнемся с ошибкой выполнения:
String s = null; // строка не указывает на объект if(s.length()==0) System.out.println("String is empty"); // ! Ошибка
Так как переменная не указывает ни на какой объект String, то соответственно мы не можем обращаться к методам объекта String.
Чтобы избежать подобных ошибок, можно предварительно проверять строку на null:
String s = null; // строка не указывает на объект if(s!=null && s.length()==0) System.out.println("String is empty");
Основные методы класса String
Основные операции со строками раскрывается через методы класса String, среди которых можно выделить следующие:
-
concat(): объединяет строки
-
valueOf(): преобразует объект в строковый вид
-
join(): соединяет строки с учетом разделителя
-
сompare(): сравнивает две строки
-
charAt(): возвращает символ строки по индексу
-
getChars(): возвращает группу символов
-
equals(): сравнивает строки с учетом регистра
-
equalsIgnoreCase(): сравнивает строки без учета регистра
-
regionMatches(): сравнивает подстроки в строках
-
indexOf(): находит индекс первого вхождения подстроки в строку
-
lastIndexOf(): находит индекс последнего вхождения подстроки в строку
-
startsWith(): определяет, начинается ли строка с подстроки
-
endsWith(): определяет, заканчивается ли строка на определенную подстроку
-
replace(): заменяет в строке одну подстроку на другую
-
trim(): удаляет начальные и конечные пробелы
-
substring(): возвращает подстроку, начиная с определенного индекса до конца или до определенного индекса
-
toLowerCase(): переводит все символы строки в нижний регистр
-
toUpperCase(): переводит все символы строки в верхний регистр
Разберем работу этих методов.
НазадВперед
JSON
Сериализация и Десериализация
JSON — невероятно удобный и полезный синтаксис для хранения и обмена данными. Java полностью поддерживает это.
Прим. перев. Для использования JSON из примера необходимо подключить библиотеку JSON Simple.
Вы можете сериализовать данные следующим образом:
Получается следующая строка JSON:
Десериализация в Java выглядит так:
Используемый в примере файл JSON (jsonDemoFile.json):
Прим. перев. В Java проектах очень часто для работы с JSON используют библиотеки Gson от Google или Jackson. Обе библиотеки очень популярны и хорошо поддерживаются. Попробуйте и их.
All String Methods
The String class has a set of built-in methods that you can use on strings.
Method | Description | Return Type |
---|---|---|
charAt() | Returns the character at the specified index (position) | char |
codePointAt() | Returns the Unicode of the character at the specified index | int |
codePointBefore() | Returns the Unicode of the character before the specified index | int |
codePointCount() | Returns the Unicode in the specified text range of this String | int |
compareTo() | Compares two strings lexicographically | int |
compareToIgnoreCase() | Compares two strings lexicographically, ignoring case differences | int |
concat() | Appends a string to the end of another string | String |
contains() | Checks whether a string contains a sequence of characters | boolean |
contentEquals() | Checks whether a string contains the exact same sequence of characters of the specified CharSequence or StringBuffer |
boolean |
copyValueOf() | Returns a String that represents the characters of the character array | String |
endsWith() | Checks whether a string ends with the specified character(s) | boolean |
equals() | Compares two strings. Returns true if the strings are equal, and false if not |
boolean |
equalsIgnoreCase() | Compares two strings, ignoring case considerations | boolean |
format() | Returns a formatted string using the specified locale, format string, and arguments | String |
getBytes() | Encodes this String into a sequence of bytes using the named charset, storing the result into a new byte array | byte[] |
getChars() | Copies characters from a string to an array of chars | void |
hashCode() | Returns the hash code of a string | int |
indexOf() | Returns the position of the first found occurrence of specified characters in a string | int |
intern() | Returns the index within this string of the first occurrence of the specified character, starting the search at the specified index | String |
isEmpty() | Checks whether a string is empty or not | boolean |
lastIndexOf() | Returns the position of the last found occurrence of specified characters in a string | int |
length() | Returns the length of a specified string | int |
matches() | Searches a string for a match against a regular expression, and returns the matches | boolean |
offsetByCodePoints() | Returns the index within this String that is offset from the given index by codePointOffset code points | int |
regionMatches() | Tests if two string regions are equal | boolean |
replace() | Searches a string for a specified value, and returns a new string where the specified values are replaced | String |
replaceFirst() | Replaces the first occurrence of a substring that matches the given regular expression with the given replacement | String |
replaceAll() | Replaces each substring of this string that matches the given regular expression with the given replacement | String |
split() | Splits a string into an array of substrings | String[] |
startsWith() | Checks whether a string starts with specified characters | boolean |
subSequence() | Returns a new character sequence that is a subsequence of this sequence | CharSequence |
substring() | Extracts the characters from a string, beginning at a specified start position, and through the specified number of character | String |
toCharArray() | Converts this string to a new character array | char[] |
toLowerCase() | Converts a string to lower case letters | String |
toString() | Returns the value of a String object | String |
toUpperCase() | Converts a string to upper case letters | String |
trim() | Removes whitespace from both ends of a string | String |
valueOf() | Returns the primitive value of a String object | String |
❮ Previous
Next ❯
Производительность конкатенации
При объединении строк вам следует остерегаться возможных проблем с производительностью. Конкатенация двух строк будет преобразована компилятором Java в нечто вроде этого:
String one = "Hello"; String two = " World"; String three = new StringBuilder(one).append(two).toString();
Создается новый StringBuilder, который передает первую строку в свой конструктор, а вторую — в свой метод append(), прежде чем вызвать метод toString(). Этот код фактически создает два объекта: экземпляр StringBuilder и новый экземпляр String, возвращенный методом toString().
При выполнении самих себя в виде одного оператора эти дополнительные затраты на создание объекта незначительны. Однако когда выполняется внутри цикла, это другая история.
Вот цикл, содержащий вышеуказанный тип конкатенации строк:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; String result = null; for(String string : strings) { result = result + string; }
Этот код будет скомпилирован в нечто похожее на это:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; String result = null; for(String string : strings) { result = new StringBuilder(result).append(string).toString(); }
Теперь для каждой итерации в этом цикле создается новый StringBuilder. Кроме того, объект String создается методом toString(). Это приводит к небольшим расходам на создание экземпляров за одну итерацию: один объект StringBuilder и один объект String. Само по себе не является настоящим убийцей производительности, хотя.
Каждый раз, когда выполняется новый код StringBuilder(result), конструктор StringBuilder копирует все символы из результирующего String в StringBuilder. Чем больше итераций цикла, тем больше будет результат String. Чем больше растет результат String, тем больше времени требуется для копирования символов из него в новый StringBuilder и повторного копирования символов из StringBuilder во временную строку, созданную методом toString(). Другими словами, чем больше итераций, тем медленнее становится каждая итерация.
Самый быстрый способ объединения строк — создать StringBuilder один раз и повторно использовать один и тот же экземпляр внутри цикла. Вот как это выглядит:
String[] strings = new String[]{"one", "two", "three", "four", "five" }; StringBuilder temp = new StringBuilder(); for(String string : strings) { temp.append(string); } String result = temp.toString();
Этот код избегает как экземпляров объектов StringBuilder и String внутри цикла, так и, следовательно, позволяет избежать двухкратного копирования символов, сначала в StringBuilder, а затем снова в String.
Поиск с помощью indexOf()
Вы можете искать подстроки в Strings, используя метод indexOf():
String string1 = "Hello World"; int index = string1.indexOf("World");
Индексная переменная будет содержать значение 6 после выполнения этого кода. Метод indexOf() возвращает индекс, в котором находится первый символ в первой соответствующей подстроке. В этом случае W совпадающей подстроки World была найдена по индексу 6. Если подстрока не найдена в строке, метод возвращает -1.
Существует версия метода indexOf(), которая берет индекс, с которого начинается поиск. Таким образом, вы можете искать в строке, чтобы найти более одного вхождения подстроки:
String theString = "is this good or is this bad?"; String substring = "is"; int index = theString.indexOf(substring); while(index != -1) { System.out.println(index); index = theString.indexOf(substring, index + 1); }
Этот код просматривает строку «это хорошо или это плохо?» для вхождений подстроки «is». Для этого используется метод indexOf(substring, index). Параметр index указывает, с какого индекса символа в строке следует начать поиск. В этом примере поиск начинается с 1 символа после индекса, в котором было найдено предыдущее вхождение.
Вывод:
0 5 16 21
Подстрока «is» находится в четырех местах. Два раза в словах «есть» и два раза внутри слова «этот».
Класс Java String также имеет метод lastIndexOf(), который находит последнее вхождение подстроки:
String theString = "is this good or is this bad?"; String substring = "is"; int index = theString.lastIndexOf(substring); System.out.println(index);
Выход — 21, который является индексом последнего вхождения подстроки «is».
1 Класс StringTokenizer
И еще несколько самых частых сценариев работы со строками. Как разбить строку на несколько частей? Для этого есть несколько способов.
Метод
Первый способ разбить строку на несколько частей — использовать метод . В него в качестве параметра нужно передать регулярное выражение: специальный шаблон строки-разделителя. Что такое регулярное выражение, вы узнаете в квесте Java Collections.
Пример:
Код | Результат |
---|---|
Результатом будет массив из трех строк: |
Просто, но иногда такой подход избыточен. Если разделителей много, например, «пробел», «enter», «таб», «точка», приходится конструировать достаточно сложное регулярное выражение. Его сложно читать, а значит, в него сложно вносить изменения.
Класс
В Java есть специальный класс, вся работа которого — разделять строку на подстроки.
Этот класс не использует регулярные выражения: вместо этого в него просто передается строка, состоящая из символов-разделителей. Преимущества этого подхода в том, что он не разбивает сразу всю строку на кусочки, а потихоньку идет от начала к концу.
Класс состоит из конструктора и двух методов. В конструктор нужно передать строку, которую мы разбиваем на части, и строку — набор символов, используемых для разделения.
Методы | Описание |
---|---|
Возвращает следующую подстроку | |
Проверяет, есть ли еще подстроки. |
Этот класс чем-то напоминает класс , у которого тоже были методы и .
Создать объект можно командой:
Где строка — это , которую будем делить на части. А — это строка, каждый символ которой считается символом-разделителем. Пример:
Код | Вывод на экран |
---|---|
Обратите внимание, что разделителем считается каждый символ строки, переданный второй строкой в конструктор
2 Класс Double
Класс , в общем-то, аналогичен классу , только является оберткой не для типа , а для типа . У него тоже есть интересные нам поля и методы, рассмотрим некоторые из них:
Интересных полей у класса шесть:
Поле | Описание |
---|---|
Минус бесконечность | |
Плюс бесконечность | |
Минимальное значение экспоненты (2x) | |
Максимальное значение экспоненты (2x) | |
Минимальное значение типа | |
Максимальное значение типа |
Бесконечность
Если вы разделите на , получите отрицательную бесконечность, если на — положительную бесконечность. Тип может не только делить на ноль, но и хранить такие значения.
Экспонента числа
С экспонентой тоже все просто. Число double внутри состоит из мантисы и экспоненты. Только вот значение экспоненты — это не , а . Если экспонента вырастет на , итоговое значение числа станет больше в два раза.
, в итоге получаем примерно равно
Также у класса есть интересные методы:
Методы | Описание |
---|---|
Возвращает строку — шестнадцатеричное представление числа | |
Проверяет, является ли переданное число бесконечностью. | |
Проверяет, является ли переданное число | |
Оборачивает переданный в | |
Возвращает число, полученное из строки |
Из интересного можно отметить наличие метода , который возвращает , если переданное в него число было плюс или минус бесконечность.
Аналогично работает и метод — проверяет, является ли переданное в него число : специальная константа, обозначающая неопределенность (Not a Number, Не число).
Класс Thread
В Java функциональность отдельного потока заключается в классе Thread. И чтобы создать новый поток, нам надо создать
объект этого класса. Но все потоки не создаются сами по себе. Когда запускается программа, начинает работать главный поток этой программы.
От этого главного потока порождаются все остальные дочерние потоки.
С помощью статического метода Thread.currentThread() мы можем получить текущий поток выполнения:
public static void main(String[] args) { Thread t = Thread.currentThread(); // получаем главный поток System.out.println(t.getName()); // main }
По умолчанию именем главного потока будет .
Для управления потоком класс Thread предоставляет еще ряд методов. Наиболее используемые из них:
-
getName(): возвращает имя потока
-
setName(String name): устанавливает имя потока
-
getPriority(): возвращает приоритет потока
-
setPriority(int proirity): устанавливает приоритет потока. Приоритет является одним из ключевых факторов для выбора
системой потока из кучи потоков для выполнения. В этот метод в качестве параметра передается числовое значение приоритета — от 1 до 10.
По умолчанию главному потоку выставляется средний приоритет — 5. -
isAlive(): возвращает true, если поток активен
-
isInterrupted(): возвращает true, если поток был прерван
-
join(): ожидает завершение потока
-
run(): определяет точку входа в поток
-
sleep(): приостанавливает поток на заданное количество миллисекунд
-
start(): запускает поток, вызывая его метод
Мы можем вывести всю информацию о потоке:
public static void main(String[] args) { Thread t = Thread.currentThread(); // получаем главный поток System.out.println(t); // main }
Консольный вывод:
Thread
Первое будет представлять имя потока (что можно получить через ), второе значение 5 предоставляет приоритет
потока (также можно получить через ), и последнее представляет имя группы потоков, к которому относится текущий — по умолчанию также main
(также можно получить через )
Недостатки при использовании потоков
Далее мы рассмотрим, как создавать и использовать потоки. Это довольно легко. Однако при создании многопоточного приложения нам следует учитывать ряд обстоятельств,
которые негативно могут сказаться на работе приложения.
На некоторых платформах запуск новых потоков может замедлить работу приложения. Что может иметь большое значение, если нам критичная производительность
приложения.
Для каждого потока создается свой собственный стек в памяти, куда помещаются все локальные переменные и ряд других данных, связанных с выполнением
потока. Соответственно, чем больше потоков создается, тем больше памяти используется. При этом надо помнить, в любой системе размеры используемой памяти ограничены.
Кроме того, во многих системах может быть ограничение на количество потоков. Но даже если такого ограничения нет, то в любом случае
имеется естественное ограничение в виде максимальной скорости процессора.
НазадВперед
Метод сравнения String equals()
Сравнение строк с помощью equals позволяет проверять исходное содержимое строки. Метод возвращает true, когда параметр — объект String, представляющий собой ту же строку символов, что и объект:
Objects.equals("Java", new String("Java")) //true
Когда надо выполнить проверку, имеют ли 2 строки одинаковое значение, мы можем задействовать Objects.equals().
class TestClass{ public static void main (String[] args) { String str1 = "Java"; String str2 = "Java"; String str3 = "ASP"; String str4 = "JAVA"; String str5 = new String("Java"); // оба равны и возвращают true if(str1.equals(str2)){ System.out.println("Statement is true"); }else{ System.out.println("Statement is false"); } // оба не равны и возвращают false if(str1.equals(str3)){ System.out.println("Statement is true"); }else{ System.out.println("Statement is false"); } // оба не равны и возвращают false if(str1.equals(str4)){ System.out.println("Statement is true"); }else{ System.out.println("Statement is false"); } // оба равны и возвращают true if(str1.equals(str5)){ System.out.println("Statement is true"); }else{ System.out.println("Statement is false"); } } }
Итог:
Statement is true Statement is false Statement is false Statement is true
Планы команды IntelliJ Platform на 2020 год
Сегодня мы хотели бы рассказать о некоторых из текущих проектов команды IntelliJ Platform, которые затронут IntelliJ IDEA и другие IDE на базе нашей платформы. Результаты этих проектов будут выпускаться в течение следующего года; некоторые из них попадут уже в релиз 2020.1, который выйдет весной. Проекты, о которых мы хотели бы рассказать, касаются двух больших областей: производительности и поддержки современных сценариев разработки.
Скорость индексации
Индексация на данный момент — одно из самых проблемных мест с производительностью наших IDE. Мы планируем подойти к ее решению с нескольких направлений.
Во-первых, мы планируем поддержать готовые фрагменты индекса. Теперь вместо того, чтобы каждая копия IntelliJ IDEA заново индексировала класс java.lang.String, мы сможем предоставить для скачивания готовый фрагмент индекса для JDK, который можно будет переиспользовать без дополнительных затрат CPU. Помимо JDK, мы изучаем возможность предоставлять готовые фрагменты индекса для библиотек из Maven Central, а также для интерпретаторов и пакетов в других IDE. Мы также хотели бы позволять командам и организациям использовать готовые фрагменты индекса для кода своих проектов, но у нас пока нет на этот счет конкретных планов.
Creating Format Strings
You have printf() and format() methods to print output with formatted numbers. The String class has an equivalent class method, format(), that returns a String object rather than a PrintStream object.
Using String’s static format() method allows you to create a formatted string that you can reuse, as opposed to a one-time print statement. For example, instead of −
Example
System.out.printf("The value of the float variable is " + "%f, while the value of the integer " + "variable is %d, and the string " + "is %s", floatVar, intVar, stringVar);
You can write −
String fs; fs = String.format("The value of the float variable is " + "%f, while the value of the integer " + "variable is %d, and the string " + "is %s", floatVar, intVar, stringVar); System.out.println(fs);
3 String Pool
Все строки, которые были заданы в коде в , во время работы программы хранятся в памяти в так называемом . — это специальный массив для хранения строк. Цель его создания — оптимизация хранения строк:
Во-первых, строки, заданные в коде, нужно все-таки где-то хранить. Код — это команды, а данные (тем более такие большие как строки) нужно хранить в памяти отдельно от кода. В коде фигурируют только ссылки на объекты-строки.
Во-вторых, все одинаковые литералы можно хранить в памяти только один раз. Так оно и работает. Когда код вашего класса загружается Java-машиной, все строковые литералы добавляются в , если их там еще нет. Если уже есть, просто используется ссылка на строку из .
Поэтому если в своем коде вы присвоите нескольким -переменным одинаковые литералы, переменные будут содержать одинаковые ссылки. В литерал будет добавлен только один раз, во всех остальных случаях будет браться ссылка на уже загруженную в строку.
Как это примерно работает:
Код | Работа с StringPoll |
---|---|
Именно поэтому переменные и будут хранить одинаковые ссылки.
Метод
Ну и самое интересное: вы можете программно добавить любую строку в . Для этого нужно просто вызвать метод у -переменной.
Метод добавит строку в , если ее еще там нет, и вернет ссылку на строку из .
Код | Примечание |
---|---|
Вряд ли вы будете часто пользоваться этим методом, однако о нем любят спрашивать на собеседованиях, поэтому лучше о нем знать, чем не знать.
Методы
Последнее обновление: 17.04.2018
Если переменные и константы хранят некоторые значения, то методы содержат собой набор операторов, которые выполняют определенные действия.
Общее определение методов выглядит следующим образом:
тип_возвращаемого_значения название_метода (){ // тело метода }
Модификаторы и параметры необязательны.
По умолчанию главный класс любой программы на Java содержит метод main, который служит точкой входа в программу:
public static void main(String[] args) { System.out.println("привет мир!"); }
Ключевые слова и являются модификаторами. Далее идет тип возвращаемого значения.
Ключевое слово указывает на то, что метод ничего не возвращает.
Затем идут название метода — main и в скобках параметры метода — . И в фигурные скобки заключено тело метода — все действия,
которые он выполняет.
Создадим еще несколько методов:
public class Program{ public static void main (String args[]){ } void hello(){ System.out.println("Hello"); } void welcome(){ System.out.println("Welcome to Java 10"); } }
Здесь определены два дополнительных метода: hello и welcome, каждый из которых выводит некоторую строку на консоль. Методы определяются внутри класса — в данном случае внутри класса Program,
в котором определен метод main.
Но если мы скомпилируем и запустим данную программу, то мы ничего не увидим на консоли. В примере выше мы определили два метода, но мы их нигде не вызываем. По умолчанию в программе Java
выполняется только метод main и все его содержимое. Поэтому, если мы хотим, чтобы другие методы тоже выполнялись, их надо вызвать в методе main.
Вызов метода осуществляется в форме:
имя_метода(аргументы);
После имени метода указываются скобки, в которых перечисляются аргументы — значения для параметров метода.
Например, определим и выполним несколько методов:
public class Program{ public static void main (String args[]){ hello(); welcome(); welcome(); } static void hello(){ System.out.println("Hello"); } static void welcome(){ System.out.println("Welcome to Java 10"); } }
В методе main вызывается один раз метод hello и два раза метод welcome. В этом и заключается одно из преимуществ методов: мы можем вынести некоторые общие действия в
отдельный метод и затем вызывать многократно их в различных местах программы. Поскольку оба метода не имеют никаких параметров, то после их названия при вызове ставятся пустые скобки.
Также следует отметить, что чтобы вызвать в методе main другие методы, которые определены в одном классе с методом main, они должны иметь модификатор
.
В итоге после компиляции и выполнения программы мы увидим на консоли:
Hello Welcome to Java 10 Welcome to Java 10
НазадВперед