Класс String
Класс String очень часто используется программистами, поэтому его следует изучить очень хорошо.
Следует помнить, что объекты класса String являются неизменяемыми (immutable). Поэтому, когда вам кажется, что вы меняете строку, то на самом деле вы создаёте новую строку.
В Java есть специальные классы StringBuffer и StringBuilder, который допускают изменения в строке.
Классы String, StringBuffer, StringBuilder определены в пакете java.lang и доступны автоматически без объявления импорта. Все три класса реализуют интерфейс CharSequence.
Создать строку очень просто. Например, можно так:
String aboutCat = "Кот - это звучит гордо, а если наступить на хвост, то громко";
Можно создать массив строк:
String[] cats = ;
Можно создать пустой объект класса String:
String str = new String();
Можно создать строку через массив символов:
char[] chars = < 'c', 'a', 't' >; String str = new String(chars);
Есть ещё конструктор, позволяющий задать диапазон символьного массива. Вам нужно указать начало диапазона и количество символов для использования:
char[] chars = ; String str = new String(chars, 0, 3);
Можно создать объект класса String из объекта классов StringBuffer и StringBuilder при помощи следующих конструкторов:
String(StringBuffer объект_StrBuf) String(StringBuilder объект_StrBuild)
Операторы + и += для String
На языке Java знак плюс (+) означает конкатенацию строк (concatenation), иными словами — объединение строк.
String cat = "Кот"; String name = "Васька"; //складываем две строки и пробел между ними, чтобы слова не слиплись String fullname = cat + "" + name; // получится Кот Васька
Если один из операндов в выражении содержит строку, то другие операнды также должны быть строками. Поэтому Java сама может привести переменные к строковому представлению, даже если они не являются строками.
int digit = 4; String paws = " лапы"; String aboutcat = digit + paws; // хотя мы складываем число и строку, но все равно получим строку
За кулисами Java за нас преобразовало число 4 в строку «4».
Форматирование строк
Предположим у нас есть строковый ресурс:
У кота по имени Барсик четыре лапы, один хвост. Ему 5 лет
Чтобы вывести эту строку программно в элементе TextView, можно использовать код:
TextView tvCatsInfo = (TextView)findViewById(R.id.textView1); tvCatsInfo.setText(R.string.aboutcat);
Представьте себе, что у вас несколько котов. Можно, конечно, завести для каждого кота свою строку. Но ведь строки очень похожи, меняются только имена и возраст. Также можно менять число лап и хвостов (что вы курите?).
В таких случаях можно применить форматирование строк. Нужно определить слова, которые мы будем менять и заменить их на специальный набор символов, которые начинаются с символа процента, затем идет число, увеличивающееся на единицу, далее $s для строк или $d для чисел. Итак, изменим наш строковой ресурс так:
У кота по имени %1$s %2$s лапы, %3$s хвост. Ему %4$d лет
Внесём изменения в код:
String strBarsik = "Барсик"; String strPaws = "четыре"; String strTail = "один"; int year = 5; String strCats = getResources().getString(R.string.aboutcat); String strFinal = String.format(strCats, strBarsik, strPaws, strTail, year); infoTextView.setText(strFinal);
Если вас есть кот Васька и ему шесть лет, то добавляем две переменные и форматируем строку
String strVaska = "Васька"; year = 6; String strFinal = String.format(strCats, strVaska, strPaws, strTail, year); infoTextView.setText(strFinal);
Здесь показан простейший пример с форматированием. Помните о нём и применяйте в нужных местах.
Строковой ресурс
Строки желательно хранить в ресурсах (о ресурсах есть отдельная статья).
Программно доступ к строковому ресурсу делается так:
String catName = getResources().getString(R.string.barsik);
Извлечь строки из строковых массивов в ресурсах
Предположим, у вас есть строковый массив, определённый в файле strings.xml под именем cats_array. Тогда получить доступ к строкам из ресурсов можно так:
Resources res = getResources(); String[] cats = res.getStringArray(R.array.cats_array);
Методы
public char charAt (int index)
Возвращает символ с указанным смещением в этой строке. Отсчёт идёт от 0. Не надо использовать отрицательные и несуществующие значения, будьте серьёзнее. Для извлечения нескольких символов используйте getChars().
String testString = "Котёнок"; char myChar = testString.charAt(2); tv.setText(Character.toString(myChar)); // выводит третий символ - т
public int codePointAt(int index)
Возвращает Unicode-символ в заданном индексе
String testString = "Котёнок"; int myChar = testString.codePointAt(3); tv.setText(String.valueOf(myChar)); // возвращает 1105
public int codePointBefore(int index)
Возвращает Unicode-символ, который предшествует данному индексу
String testString = "Котёнок"; int myChar = testString.codePointBefore(4); tv.setText(String.valueOf(myChar)); // возвращает 1105
public int codePointCount(int start, int end)
Вычисляет количество Unicode-символов между позициями start и end
String testString = "Котёнок"; int myChar = testString.codePointCount(0, 3); tv.setText(String.valueOf(myChar)); // возвращает 3
public int compareTo(String string)
Сравнивает указанную строку, используя значения символов Unicode и вычисляет, какая из строк меньше, равна или больше следующей. Может использоваться при сортировке. Регистр учитывается. Если строки совпадают, то возвращается 0, если меньше нуля, то вызывающая строка меньше строки string, если больше нуля, то вызывающая строка больше строки string. Слова с большим регистром стоят выше слова с нижним регистром.
String testString = "Котёнок"; if (testString.compareTo("котёнок") == 0) < tvInfo.setText("Строки равны"); >else < tvInfo.setText("Строки не равны. Возвращено" + testString.compareTo("котёнок")); // возвращает -32 >
Отсортируем массив строк через пузырьковую сортировку.
String[] poem = < "Мы", "везём", "с", "собой", "кота" >; for (int j = 0; j < poem.length; j++) < for (int i = j + 1; i < poem.length; i++) < if (poem[i].compareTo(poem[j]) < 0) < String temp = poem[j]; poem[j] = poem[i]; poem[i] = temp; >> System.out.println(poem[j]); >
В результате мы получим:
Мы везём кота с собой
Как видите, от перемены мест слагаемых сумма сортировки коты не меняются.
public int compareToIgnoreCase (String string)
Сравнивает указанную строку, используя значения символов Unicode, без учёта регистра.
String testString = "Котёнок"; if (testString.compareToIgnoreCase("котёнок") == 0) < tv.setText("Строки равны"); // слова одинаковы, если не учитывать регистр >else
public String concat (String string)
Объединяет строку с указанной строкой. Возвращается новая строка, которая содержит объединение двух строк. Обратите внимание, что само имя метода содержит кота!
String testString = "Сук"; String newString = testString.concat("кот"); tv.setText(newString);
Метод выполняет ту же функцию, что и оператор + и можно было написать Сук + кот . Но настоящий кошатник будет использовать «кошачий» метод.
public boolean contains (CharSequence cs)
Определяет, содержит ли строка последовательность символов в CharSequence
String testString = "котёнок"; if(testString.contains("кот"))
public boolean contentEquals(CharSequence cs)
Сравнивает CharSequence с этой строкой.
public boolean contentEquals(StringBuffer strbuf)
Сравнивает StringBuffer с этой строкой
public static String copyValueOf(char[] data)
Создаёт новую строку, содержащую символы из указанного массива. Изменение массива после создания строки не изменяет созданную строку.
char[] textArray = ; String newString = String.copyValueOf(textArray); infoTextView.setText(newString);
public static String copyValueOf (char[] data, int start, int length)
Создаёт новую строку, содержащую указанные символы из массива data начиная с позиции start (нумерация начинается с нуля) длинной length.
Если указать индекс вне границ строки, то возникнет исключение StringIndexOutOfBoundsException.
char[] textArray = ; String newString = String.copyValueOf(textArray, 7, 4); infoTextView.setText(newString);
public boolean endsWith(String suffix)
Проверяет, заканчивается ли строка символами suffix.
String str1 = "Суккот"; if(str1.endsWith("кот")) infoTextView.setText("Слово заканчивается на котике"); else infoTextView.setText("Плохое слово. Нет смысла его использовать");
public boolean equals (Object string)
Сравнивает указанный объект и строку и возвращает true, если сравниваемые строки равны, т.е. содержит те же символы и в том же порядке с учётом регистра.
String str1 = "Кот"; String str2 = "Кошка"; if(str1.equals(str2)) infoTextView.setText("Строки совпадают"); else infoTextView.setText("Строки не совпадают");
Не путать метод с оператором ==, который сравнивает две ссылки на объекты и определяет, ссылаются ли они на один и тот же экземпляр. Смотри пункт Сравнение строк: equals() или ==?
public boolean equalsIgnoreCase(String string)
Сравнивает указанную строку с исходной строкой без учёта регистра и возвращает true, если они равны. Диапазон A-Z считается равным диапазону a-z.
String str1 = "Кот"; String str2 = "кот"; if(str1.equalsIgnoreCase(str2)) infoTextView.setText("Строки совпадают"); else infoTextView.setText("Строки не совпадают");
public static String format(Locale locale, String format, Object. args)
Возвращает отформатированную строку, используя прилагаемый формат и аргументы, локализованных в данной области. Например дату или время
// выводим число типа float с двумя знаками после запятой String.format("%.2f", floatValue);
Склеиваем два слова, которые выводятся с новой строки. При этом второе слово выводится в верхнем регистре.
String str1 = "Кот"; String str2 = "васька"; String strResult = String.format("%s\n%S", str1, str2); // выводим результат в TextView infoTextView.setText(strResult);
Конвертируем число в восьмеричную систему.
String str1 = "8"; int inInt = Integer.parseInt(str1); // конвертируем строку в число String strResult = String.format("(Восьмеричное значение): %o\n", inInt); infoTextView.setText(strResult);
По аналогии выводим в шестнадцатеричной системе
String str1 = "255"; int inInt = Integer.parseInt(str1); String strResult = String.format("(Шестнадцатеричное значение): %x\n", inInt); // число 255 будет выведено как ff infoTextView.setText(strResult);
Для верхнего регистра используйте %X, тогда вместо ff будет FF.
Для десятичной системы используйте %d.
Дату тоже можно выводить по разному.
Date now = new Date(); Locale locale = Locale.getDefault(); infoTextView.setText( String.format(locale, "%tD\n", now) + // (MM/DD/YY) String.format(locale, "%tF\n", now) + // (YYYY-MM-DD) String.format(locale, "%tr\n", now) + // Full 12-hour time String.format(locale, "%tz\n", now) + // Time zone GMT offset String.format(locale, "%tZ\n", now)); // Localized time zone abreviation
Допустим, при выводе double получается 3.0. Как вывести 3, т.е. без нуля. И с учётом того, что например 3.1 должно выводиться как 3.1. Округление здесь не поможет.
public static String fmt(double d) < if (d == (long) d) < return String.format("%d", (long) d); >else < return String.format("%s", d); >>
public byte[] getBytes()
Конвертируем строку в набор байтов.
String catName = "Барсик"; byte[] myByte = catName.getBytes(); Log.i(TAG, myByte.toString()); Log.i(TAG, new String(myByte)); // из массива байтов обратно в строку
public byte[] getBytes(String charsetName)
Возвращает отформатированную строку, используя прилагаемую кодировку.
String catName = "Барсик"; byte[] myByte = catName.getBytes(StandardCharsets.UTF_8); Log.i(TAG, myByte.toString()); Log.i(TAG, new String(myByte, StandardCharsets.UTF_8));
public void getBytes(int start, int end, byte[] data, int index) и другие перегруженные версии
Метод сохраняет символы в массив байтов, альтернатива методу getChars(). Часто используется при экспорте строк из различных источников, где используются другие символы Unicode. Например, Java по умолчанию использует 16-битовые символы Unicode, а в интернете часто строки используют 8-битовый код Unicode, ASCII и др.
public void getChars(int start, int end, char[] buffer, int index)
Метод для извлечения нескольких символов из строки. Вам надо указать индекс начала подстроки (start), индекс символа, следующего за концом извлекаемой подстроки (end). Массив, который принимает выделенные символы находится в параметре buffer. Индекс в массиве, начиная с которого будет записываться подстрока, передаётся в параметре index. Следите, чтобы массив был достаточного размера, чтобы в нём поместились все символы указанной подстроки.
String unusualCat = "Котёнок по имени Гав"; int start = 5; int end = 12; char[] buf = new char[end - start]; unusualCat.getChars(start, end, buf, 0); infoTextView.setText(new String(buf));
public int hashCode()
Возвращает целое число — хэш-код для данного объекта.
public int indexOf(int ch)
Ищет появление указанного символа и возвращает позицию индекса. Если символа нет, то возвращается -1.
String testString = "котёнок"; // символ ё встречается в четвёртой позиции (index = 3) infoTextView.setText(String.valueOf(testString.indexOf('ё')));
public int indexOf (int ch, int fromIndex)
Ищет индекс символа сh, начиная с позиции fromIndex
String testString = "котёнок"; // вернёт -1, так как после 5 символа буквы ё нет infoTextView.setText(String.valueOf(testString.indexOf('ё', 4)));
public int indexOf (String str)
Ищет подстроку str и возвращает индекс найденной подстроки. Если подстроки не существует, то возвращается -1.
String testString = "У окошка"; infoTextView.setText(String.valueOf(testString.indexOf("кошка")));
public int indexOf (String str, int fromIndex)
Ищет подстроку str, начиная с позиции fromIndex и возвращает индекс найденной подстроки. Если подстроки не существует, то возвращается -1.
String testString = "У окошка"; infoTextView.setText(String.valueOf(testString.indexOf("кошка", 2)));
Смотри также схожий метод lastIndexOf().
public String intern ()
public boolean isEmpty ()
Проверяет, является ли строка пустой
if(catname.isEmpty()) < // здесь ваш код >
Данный метод появился в API 9 (Android 2.1). Для старых устройств используйте String.length() == 0
public int lastIndexOf (String string) и другие перегруженные версии
Метод ищет в строке в обратном порядке и возвращает индекс последнего появления указанного символа. Если указанный символ не найден, то возвратится -1. Например, получить имя файла без расширения можно так:
filename.toString().substring(0, filename.getString().lastIndexOf("."));
public static String join (CharSequence delimiter, CharSequence. elements)
Метод появился в API 26. Склеивает слова указанным разделителем. Если слово является null, то null будет использоваться в качестве слова. Есть перегруженная версия.
String message = String.join("-", "Cat", "is", "cool"); // Cat-is-cool
В этом примере мы получаем позицию последней точки и получаем подстроку до неё.
public int length()
Возвращает длину строки
String testString = "котёнок"; infoTextView.setText(String.valueOf(testString.length())); // возвращает 7 (семь символов)
public boolean matches(String regularExpression)
Проверяет, соответствует ли строка регулярным выражениям.
public int offsetByCodePoints (int index, int codePointOffset)
Возвращает позицию, расположенную на расстоянии codePointOffset после начальной позиции, заданной параметром index
public boolean regionMatches (int thisStart, String string, int start, int length)
Метод сравнивает указанную часть строки с другой частью строки. Нужно задать индекс начала диапазон строки вызывающего объекта класса String. Строка для сравнивания передаётся в параметре string. Индекс символа, начиная с которого нужно выполнять сравнение передаётся в параметре start, а длина сравниваемой подстроки в параметре length.
public boolean regionMatches (boolean ignoreCase, int thisStart, String string, int start, int length)
Перегруженная версия. Метод сравнивает указанную часть строки с другой частью строки, игнорируя регистр.
public String replace(CharSequence target, CharSequence replacement) и другие перегруженные версии
Меняет символ или последовательность символов target на replacement
String source = "кит"; // меняем символы и на о infoTextView.setText(source.replace('и', 'о')); String source = "компот"; // меняем подстроку омпо на о infoTextView.setText(source.replace("омпо", "о")); // возвращается кот
public String replaceAll (String regularExpression, String replacement)
int i = Integer.parseInt("kitty123".replaceAll("[\\D]","")); int j = Integer.parseInt("123kitty".replaceAll("[\\D]","")); int k = Integer.parseInt("1k2it3ty".replaceAll("[\\D]","")); // Вернёт i = 123; j = 123; k = 123;
Смотри также пример в задачнике — Удаление гласных из строки.
public String replaceFirst (String regularExpression, String replacement)
Удаляет первые символы при помощи регулярного выражения.
Например, если нужно удалить нули в начале чисел 001, 007, 000024, то можно использовать такой вызов.
String s = "001234-cat"; String s = s.replaceFirst ("^0*", ""); // останется 1234-cat
public String[] split (String regularExpression) и другие перегруженные версии
Разбивает строку на массив из слов. Например, есть строка Васька Рыжик Мурзик Барсик и мы хотим получить массив имён котов:
String catNames = "Васька Рыжик Мурзик Барсик"; String aCats[] = catNames.split(" "); // по пробелу
aCats[0] = Васька
aCats[1] = Рыжик
aCats[2] = Мурзик
aCats[3] = Барсик
Также можно использовать регулярное выражение \\s+, чтобы учитывать любые типы пробелов, включая двойные и более пробелы подряд.
String[] words = someString.split("\\s+");
Будьте аккуратны при разбиении по запятой. Часто после запятой идёт пробел, поэтому нужно правильно установить разделитель.
String catNames = "Васька, Рыжик, Мурзик, Барсик"; String aCats[] = catNames.split("; "); // по запятой с пробелом
Если исходная строка начинается с разделителя, первым элементом результирующего массива будет пустая строка. Но если исходная строка заканчивается разделителем, то пустой строки не будет.
У перегруженной версии метода есть дополнительный параметр limit, определяющий, какое количество раз шаблон regex будет применяться к исходной строке.
Также следует быть аккуратным с разделителем |. В регулярных выражениях | является специальным символом. Чтобы использовать вертикальную черту в качестве разделителя, нужно экранировать этот символ с помощью двух обратных слешей «\\|».
public boolean startsWith(String prefix)
Проверяет, начинается ли строка символами prefix с начала строки
String str1 = "котлета"; if(str1.startsWith("кот")) infoTextView.setText("Слово содержит кота"); else infoTextView.setText("Плохое слово. Нет смысла его использовать");
public boolean startsWith(String prefix, int start)
Проверяет, начинается ли заданная строка символами prefix с указанной позиции.
String str1 = "Суккот"; if(str1.startsWith("кот", 3)) infoTextView.setText("Слово содержит кота"); else infoTextView.setText("Плохое слово. Нет смысла его использовать");
public CharSequence subSequence (int start, int end)
Аналогичен методу substring(), но может использоваться для CharSequence.
public String substring(int start) и другие перегруженные версии
Создаёт новую последовательность/строку с символами из данной строки начиная с позиции start до конца строки/заканчивая символом с позиции end. Новая строка содержит символы от start до end — 1, поэтому берём на один символ больше.
String testString = "скотина"; infoTextView.setText(testString.substring(1, 4)); // возвращается кот
Если указать индекс вне границ строки, то возникнет исключение StringIndexOutOfBoundsException.
public char[] toCharArray()
Копирует символы в этой строке в массив символов. Тот же результат можно получить через метод getChars(). Документация не рекомендует использовать данный метод, предлагая метод charAt().
String unusualCat = "Котёнок по имени Гав"; char[] yomoe = unusualCat.toCharArray(); infoTextView.setText(String.valueOf(yomoe[3]));
public String toLowerCase() и другие перегруженные версии
Преобразовывает строку в нижний регистр. Преобразованием управляет заданный по умолчанию региональный язык.
String cat = "Кот"; String lower = cat.toLowerCase(); infoTextView.setText(lower);
public String toString ()
Возвращает строку. Для самой строки, которая сама уже является строкой, возвращать строку бессмысленно (о, как я загнул). Но на самом деле этот метод очень полезен для других классов.
public String toUpperCase()
Преобразовывает строку в верхний регистр. Преобразованием управляет заданный по умолчанию региональный язык.
String cat = "Кот"; String upper = cat.toUpperCase(); infoTextView.setText(upper);
public String trim()
Удаляет пробелы в начале и в конце строки.
String str = " Hello Kitty ".trim(); infoTextView.setText(str);
public static String valueOf(long value) и другие перегруженные версии
Конвертирует содержимое (числа, объекты, символы, массивы символов) в строку.
int catAge = 7; // это число infoTextView.setText(String.valueOf(catAge)); // преобразовано в строку
Генерируем случайную строку
Допустим, нам нужна случайная строка из заданных символов.
private static final String mCHAR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; private static final int STR_LENGTH = 9; // длина генерируемой строки Random random = new Random(); public void onClick(View view) < TextView infoTextView = (TextView) findViewById(R.id.textViewInfo); infoTextView.setText(createRandomString()); >public String createRandomString() < StringBuilder builder = new StringBuilder(); for (int i = 0; i < STR_LENGTH; i++) < int number = random.nextInt(mCHAR.length()); char ch = mCHAR.charAt(number); builder.append(ch); >return builder.toString(); >
Сравнение строк: equals() или ==?
String str1 = "Мурзик"; String str2 = new String(str1); boolean isCat = str1 == str2; infoTextView.setText(str1 + " == " + str2 + " -> " + isCat);
Хотя в двух переменных содержится одно и то же слово, мы имеем дело с двумя разными объектами и оператор == вернёт false.
Однажды, когда деревья были большими, мне понадобилось сравнить две строки из разных источников. Хотя строки выглядели совершенно одинаково, сравнение при помощи оператора == возвращало false и путало мне все карты. И только потом я узнал, что нужно использовать метод equals(). Строка в Java — это отдельный объект, который может не совпадать с другим объектом, хотя на экране результат выводимой строки может выглядеть одинаково. Просто Java в случае с логическим оператором == (а также !=) сравнивает ссылки на объекты (при работе с примитивами такой проблемы нет):
String s1 = "hello"; String s2 = "hello"; String s3 = s1; String s4 = "h" + "e" + "l" + "l" + "o"; String s5 = new String("hello"); String s6 = new String(new char[]); infoTextView.setText(s1 + " == " + s2 + ": " + (s1 == s2)); // попробуйте и другие варианты // infoTextView.setText(s1 + " equals " + s2 + ": " + (s1.equals(s2))); // infoTextView.setText(s1 + " == " + s3 + ": " + (s1 == s3)); // infoTextView.setText(s1 + " equals " + s3 + ": " + (s1.equals(s3))); // infoTextView.setText(s1 + " == " + s4 + ": " + (s1 == s4)); // infoTextView.setText(s1 + " equals " + s4 + ": " + (s1.equals(s4))); // infoTextView.setText(s1 + " == " + s5 + ": " + (s1 == s5)); // false // infoTextView.setText(s1 + " equals " + s5 + ": " + (s1.equals(s5))); // infoTextView.setText(s1 + " == " + s6 + ": " + (s1 == s6)); // false // infoTextView.setText(s1 + " equals " + s6 + ": " + (s1.equals(s6)));
Сортировка символов в строке
Есть несколько способов сортировки символов в заданной строке. Рассмотрим их.
Способ первый. Конвертируем строку в массив символов через toCharArray(). Запускаем два цикла. При сравнении символов нужно учитывать их регистр, поэтому мы не только сравниваем разные символы, но и одинаковые, чтобы символы в верхнем и нижнем регистре тоже были отсортированы.
public void onClick(View view) < String myString = "Котёнок"; char[] charArray = myString.toCharArray(); for (int i = 0; i < charArray.length; i++) < for (int j = i + 1; j < charArray.length; j++) < if (Character.toLowerCase(charArray[j]) < Character.toLowerCase(charArray[i])) < swapChars(i, j, charArray); >> > System.out.println("Sorted string " + String.valueOf(charArray)); > private void swapChars(int i, int j, char[] charArray)
Способ прекрасно работает на английских символах. Но строка «Котёнок» даст неправильный результат: Ккноотё. Символ «ё» попал в самый конец массива.
Способ второй. Обходимся без циклов и используем метод sort().
String myString = "Котёнок"; char[] charArray = myString.toCharArray(); Arrays.sort(charArray); System.out.println("Sorted string " + String.valueOf(charArray));
Проблема с «ё» осталась. При этом появилась другая проблема — сначала идут символы в верхнем регистре, потом в нижнем. Получилось КОкнотё.
Переписываем пример с использованием Comparator.
String myString = "КотёнОк"; Character[] charArray = new Character[myString.length()]; for(int i = 0; i < myString.length(); i++)< charArray[i] = myString.charAt(i); >Arrays.sort(charArray, Comparator.comparingInt(Character::toLowerCase)); StringBuilder stringBuilder = new StringBuilder(charArray.length); for(Character character : charArray) < stringBuilder.append(character.charValue()); >System.out.println("Sorted string " + stringBuilder.toString());
Проблема с «ё» осталась, но с регистрами всё хорошо.
Кстати, в Java 8 можно использовать Stream для подобных операций. В любом случае будьте внимательные с символами другой локали. Ни один пример не решил наших проблем.
StringTokenizer
Класс StringTokenizer разбивает строку на токены с указанным разделителем.
StringTokenizer tokenizer = new StringTokenizer("Кот Васька", " "); while (tokenizer.hasMoreElements()) < System.out.println(tokenizer.countTokens() + " words remaining to print"); System.out.println(tokenizer.nextToken()); >/* 2 words remaining to print Кот 1 words remaining to print Васька */
Перевернуть строку
Рассмотрим различные способы решения задачи.
Первый способ — представить строку в виде массива символов. Затем проходимся по всей длине массива с конца и получаем новую строку.
String catName = "Барсик"; char[] array = catName.toCharArray(); String reversed = ""; for (int i = array.length - 1; i >= 0; i--) < reversed = reversed + array[i]; >mInfoTextView.setText(reversed);
Можно не создавать массив символов, а извлекать каждый символ через метод charAt() и снова использовать цикл, прибавляя к символу предыдущую строку.
String catName = "Барсик"; String reversed = ""; for (int i = 0; i < catName.length(); i++) < reversed = catName.charAt(i) + reversed; >mInfoTextView.setText(reversed);
Можно воспользоваться готовым методом reverse() класса StringBuffer/StringBuilder.
String catName = "Барсик"; String reversed; reversed = new StringBuilder(catName).reverse().toString(); mInfoTextView.setText(reversed);
Экзотический способ при помощи редко используемого класса Stack.
Разбиваем строку на массив символов и кладём каждый символ в стек. Далее начинаем брать элементы с верхушки стека. Из-за особенностей стека (первый вошёл, последний вышел), элементы будут браться задом-наперёд и мы получим нужный результат.
String catName = "Барсик"; String reversed = ""; Stack stack = new Stack<>(); for (Character character : catName.toCharArray()) < stack.add(character); >while (!stack.isEmpty()) < reversed = reversed + stack.pop(); >mInfoTextView.setText(reversed);
Особо упоротые программисты могут написать примеры с использованием рекурсии и побитового оператора XOR. Эти варианты не будем рассматривать.
Строки в Java, методы класса String
Для работы со строками в Java существует класс String. И для объявления новой строки можно использовать один из способов:
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 – это кол-во символов. То есть, строка str4 содержит строку «come».
Важной особенностью строк в Java является их неизменяемость. Это значит, что в строке нельзя попросту изменить какой-либо символ и получить другую строку. Все строки создаются и существуют в неизменном виде, пока не будут уничтожены (как правило, автоматически сборщиком мусора). А переменные str1, str2, str3 и str4 следует воспринимать лишь как ссылки на эти строки. То есть, в любой момент в программе можно записать такую конструкцию:
str1 = str3;
что означает изменение ссылки str1 на строку «hello», на которую указывает ссылка str3. Соответственно, если на первую строку «Java» не будет указывать никакая ссылка, то она автоматически уничтожается.
Разберем работу часто используемых методов класса String. Первый метод, как написано, возвращает длину строки. Например, если нам дана вот такая строка
String str1 = "Java";
то метод length() вернет значение 4
System.out.println(str1.length()); // 4
Далее, если к строке str2
String str2 = "Hello World!";
применить метод toCharArray():
char[] helloArray = str1.toCharArray();
то получим массив символов с содержимым этой строки. Следующий пример. У нас есть пустая строка
тогда мы можем определить это, например, так:
if(s.length() == 0) System.out.println("String is empty");
if(s isEmpty()) System.out.println("String is empty");
Но, если строка задана вот так:
String s = null;
то это означает, что ссылка s не указывает ни на какой класс String и, соответственно, мы не можем вызывать методы этого класса. В этом случае проверку следует делать так:
if(s != null && s.length() == 0) System.out.println("String is empty");
мы здесь сначала проверяем: указывает ли ссылка s на объект класса и если это так, то только потом будет идти обращение к методу length().
Объединение строк
Для соединения строк можно использовать операцию сложения («+»):
String str1 = "Java"; String str2 = "Hello"; String str3 = str1 + " " + str2; System.out.println(str3); // Hello Java
При этом если в операции сложения строк используется не строковый объект, например, число, то этот объект преобразуется к строке:
String str4 = "Год " + 2015;
Еще один метод объединения — метод join() позволяет объединить строки с учетом разделителя. Например, две строки
String str1 = "Java"; String str2 = "Hello";
будут сливаться в одно слово «HelloJava», если их объединить с помощью оператора +:
String str3 = str1 + str2;
но если мы хотим, чтобы две подстроки при соединении были разделены пробелом, то можно воспользоваться методом join() следующим образом:
String str3 = String.join(" ", str2, str1); // Hello Java
В общем случае вместо пробела здесь можно ставить любой разделитель в виде строки.
Обратите внимание, что каждый раз при объединении строк мы получали новую строку как результат объединения.
Извлечение символов и подстрок
Для извлечения символов по индексу в классе String определен метод
char charAt(int index)
Он принимает индекс, по которому надо получить символов, и возвращает извлеченный символ:
String str = "Java"; char c = str.charAt(2); System.out.println(c); // v
(здесь как и в массивах первый индекс равен 0).
Если надо извлечь сразу группу символов или подстроку, то можно использовать метод
getChars(int srcBegin, int srcEnd, char[] dst, int dstBegin)
- srcBegin: индекс строки, с которого начинается извлечение символов;
- srcEnd: индекс строки, до которого идет извлечение символов;
- dst: массив символов, в который будут извлекаться символы;
- dstBegin: индекс массива dst, с которого надо добавлять извлеченные из строки символы.
String str = "Hello world!"; int start = 6; int end = 11; char[] dst=new char[end - start]; str.getChars(start, end, dst, 0); System.out.println(dst); // world
Сравнение строк
Для простого сравнения строк используются методы equals() (с учетом регистра) и equalsIgnoreCase() (без учета регистра). Оба метода в качестве параметра принимают строку, с которой сравниваются:
String str1 = "Hello"; String str2 = "hello"; System.out.println(str1.equals(str2)); // false System.out.println(str1.equalsIgnoreCase(str2)); // true
Обратите внимание, что в отличие сравнения числовых и других данных примитивных типов для сравнения строк не рекомендуется использовать оператор ==. То есть, записывать вот такое сравнение лучше не использовать:
if(str1 == str2) System.out.println("Сроки равны");
(хотя, оно тоже будет работать). Вместо этого следует использовать метод equals() класса String. Другая пара методов: int compareTo(String str) и int compareToIgnoreCase(String str) также сравнивают строки между собой, но в отличие от equals() они еще позволяют узнать больше ли одна строка другой или нет. Если возвращаемое значение этих методов больше 0, то первая строка больше второй, если меньше нуля, то, наоборот, вторая больше первой. Если строки равны, то возвращается 0. Для определения больше или меньше одна строка, чем другая, используется лексикографический порядок. То есть, например, строка «A» меньше, чем строка «B», так как символ ‘A’ в алфавите стоит перед символом ‘B’. Если первые символы строк равны, то в расчет берутся следующие символы. Например:
String str1 = "hello"; String str2 = "world"; String str3 = "hell"; System.out.println(str1.compareTo(str2)); // -15 - str1 меньше чем str2 System.out.println(str1.compareTo(str3)); // 1 - str1 больше чем str3 System.out.println(str1.compareTo(str1)); // 0 - str1 равна str1
- ignoreCase: надо ли игнорировать регистр символов при сравнении (если значение true, то регистр игнорируется);
- toffset: начальный индекс в вызывающей строке, с которого начнется сравнение;
- other: строка, с которой сравнивается вызывающая;
- oofset: начальный индекс в сравниваемой строке, с которого начнется сравнение;
- len: количество сравниваемых символов в обеих строках.
String str1 = "Hello world"; String str2 = "I work"; boolean result = str1.regionMatches(6, str2, 2, 3); System.out.println(result); // true
Поиск в строке
Метод indexOf() находит индекс первого вхождения подстроки в строку, а метод lastIndexOf() — индекс последнего вхождения. Если подстрока не будет найдена, то оба метода возвращают -1:
String str = "Hello world"; int index1 = str.indexOf('l'); // 2 int index2 = str.indexOf("wo"); //6 int index3 = str.lastIndexOf('l'); //9 System.out.println(index1+" "+index2+" "+index3);
Метод startsWith() позволяют определить начинается ли строка с определенной подстроки, а метод endsWith() позволяет определить заканчивается строка на определенную подстроку:
String str = "myfile.exe"; boolean start = str.startsWith("my"); //true boolean end = str.endsWith("exe"); //true System.out.println(start+" "+end);
Замена в строке
Метод replace() позволяет заменить в строке одну последовательность символов на другую:
String str = "Hello world"; String replStr1 = str.replace('l', 'd'); // Heddo wordd String replStr2 = str.replace("Hello", "Bye"); // Bye world System.out.println(replStr1); System.out.println(replStr2);
Обрезка строк
Метод trim() позволяет удалить начальные и конечные пробелы:
String str = " hello world "; str = str.trim(); // hello world System.out.println(str);
Метод substring() возвращает подстроку, начиная с определенного индекса до конца или до определенного индекса:
String str = "Hello world"; String substr1 = str.substring(6); // world String substr2 = str.substring(3,5); //lo System.out.println(substr1); System.out.println(substr2);
Изменение регистра
Метод toLowerCase() переводит все символы строки в нижний регистр, а метод toUpperCase() — в верхний:
String str = "Hello World"; System.out.println(str.toLowerCase()); // hello world System.out.println(str.toUpperCase()); // HELLO WORLD
Разбиение строки на подстроки
Метод split() позволяет разбить строку на подстроки по определенному разделителю. Разделитель – это какой-нибудь символ или набор символов (передается в качестве параметра). Например, разобьем текст на отдельные слова (учитывая, что слова разделены пробелом):
String text = "Я люблю язык Java!"; String[] words = text.split(" "); for(String word : words) System.out.println(word);
Что такое string в java
В примере вывода имени файла зачем указан комментарий //9? вывод программы будет Futurama.mp4 Разве не это должно быть указано в комментарии?
Anatoly Уровень 22
18 августа 2023
2 августа 2023
Почему у вас почти везде в темах есть ссылки на другие темы/источники/подтемы и у них свои такие же ссылки. Ну сколько можно? Это неудобно становится учить.
Never Ending Pie Throwing Robot Уровень 30
16 июля 2023
хорошая статья! именно так должны выглядеть дополнительные материалы к уровню!
Ислам Уровень 32
17 мая 2023
Fl1s Уровень 41
12 мая 2023
Едем дальше
zero to hero Уровень 35
6 марта 2023
Думаю что не я один такой с немым вопросом в голове: как запомнить это?
T1dehunter Уровень 24
25 февраля 2023
многое пока не понял, прочту ещё раз уровня через 3)
А. К. Уровень 13
19 января 2023
Пожалуйста, скажите, что означает вторая строка?
String[] peopleArray = people.split("; "); for (String human : peopleArray)
Николай Уровень 12
15 января 2023
Сообщество
JavaRush — это интерактивный онлайн-курс по изучению Java-программирования c нуля. Он содержит 1200 практических задач с проверкой решения в один клик, необходимый минимум теории по основам Java и мотивирующие фишки, которые помогут пройти курс до конца: игры, опросы, интересные проекты и статьи об эффективном обучении и карьере Java‑девелопера.
Подписывайтесь
Язык интерфейса
"Программистами не рождаются" © 2023 JavaRush
Скачивайте наши приложения
"Программистами не рождаются" © 2023 JavaRush
Этот веб-сайт использует данные cookie, чтобы настроить персонально под вас работу сервиса. Используя веб-сайт, вы даете согласие на применение данных cookie. Больше подробностей — в нашем Пользовательском соглашении.
Что такое string в java
Поясним результат. Строки str1 и str2 добавлены в пул строк на этапе компиляции. Во время выполнения программы происходит конкатенация строки «interned» со значением строки str2, с последующим интернированием получившейся строки в пул строк (благодаря методу intern()). Но, так как пул строк уже содержит строку «interned TopJava», объекту String str3 будет присвоена ссылка на строку в пуле строк и, соответственно, выражение равенства ссылок «==» будет истинным.
Принимая во внимание всё вышесказанное, вы можете спросить: «Почему бы все строки сразу после их создания не добавлять в пул строк? Ведь это приведет к экономии памяти…». Да, среди достаточно большого количества программистов такое заблуждение присутствует. Именно заблуждение, поскольку не все учитывают дополнительные затраты виртуальной машины на процесс интернирования, а также падение производительности, в целом. Тесты и наглядное подтверждение этого приводятся в видео докладе Алексея Шипилёва — «Катехизис java.lang.String». Финализируя доклад Алексея можно сказать, что интернирование (в виде применения метода intern ()) рекомендуется вообще не использовать. Вместо интернирования необходимо использовать дедупликацию (рассматривается далее).
