Глиф Учебники

Урок 7. Строки: String и StringBuilder

Курс «Java» · урок 7 из 10 · 3 минуты чтения

Строка — последовательность символов: слово, предложение, целый текст. В Java строки хранит класс String. Строку записывают в двойных кавычках, а одиночный символ (char) — в одинарных: "А" — строка, 'А' — символ.

Основные методы

Java
public class Main {
    public static void main(String[] args) {
        String s = "Привет, Java";
        System.out.println(s.length());
        System.out.println(s.charAt(0));
        System.out.println(s.toUpperCase());
        System.out.println(s.indexOf("Java"));
        System.out.println(s.substring(8));
        System.out.println(s.substring(0, 6));
        System.out.println(s.contains("Java"));
        System.out.println(s.replace("Java", "мир"));
    }
}
Вывод
12
П
ПРИВЕТ, JAVA
8
Java
Привет
true
Привет, мир

Символы строки нумеруются, как элементы массива, с нуля: в "Привет, Java" буква П имеет номер 0, запятая — 6, пробел — 7, J — 8.

String s = "Привет, Java"; 0 1 2 3 4 5 6 7 8 9 10 11 П р и в е т , J a v a s.substring(0, 6) "Привет" 6 не входит s.substring(8) "Java" s.length() = 12 s.charAt(0) = 'П' s.indexOf("Java") = 8
В строке "Привет, Java" двенадцать символов с номерами от 0 до 11: substring(0, 6) берёт символы 0–5 без шестого — «Привет», substring(8) — с восьмого до конца, «Java», а indexOf("Java") равен 8.
МетодЧто делает
length()длина строки (со скобками, в отличие от массива)
charAt(i)символ с номером i
substring(a)часть строки с номера a до конца
substring(a, b)часть с номера a до b, не включая b
indexOf(t)номер первого вхождения t или −1, если его нет
contains(t)есть ли t в строке
startsWith(t), endsWith(t)начинается или заканчивается ли строка на t
replace(a, b)заменяет все a на b
toUpperCase(), toLowerCase()все буквы большие или маленькие
trim()убирает пробелы по краям
isEmpty()строка пустая — длина 0
isBlank()пустая или только из пробелов (с Java 11)
repeat(n)строка, повторённая n раз (с Java 11)

Строки не меняются

Строку в Java нельзя изменить. Методы вроде toUpperCase и replace не трогают исходную строку, а возвращают новую. Если результат никуда не сохранить, он пропадёт:

Java
public class Main {
    public static void main(String[] args) {
        String name = "anna";
        name.toUpperCase();
        System.out.println(name);
        name = name.toUpperCase();
        System.out.println(name);
    }
}
Вывод
anna
ANNA

Первый вызов создал строку ANNA и тут же её выбросил. Чтобы переменная изменилась, результат нужно присвоить ей.

name.toUpperCase(); name "anna" name не изменилась toUpperCase() "ANNA" сразу потеряна name = name.toUpperCase(); name name "anna" больше не нужна toUpperCase() "ANNA"
name.toUpperCase() создаёт новую строку "ANNA", но name по-прежнему ссылается на "anna"; только после name = name.toUpperCase() переменная переходит к новой строке.

Обход по символам

Java
public class Main {
    public static void main(String[] args) {
        String text = "мама мыла раму";
        int count = 0;
        for (int i = 0; i < text.length(); i++) {
            if (text.charAt(i) == 'а') {
                count++;
            }
        }
        System.out.println(count);
    }
}
Вывод
4

Символы (char) можно сравнивать через == — это просто числа-коды. То же можно записать через for-each: for (char c : text.toCharArray()).

Разбить и склеить

Java
public class Main {
    public static void main(String[] args) {
        String line = "яблоко,груша,слива";
        String[] parts = line.split(",");
        System.out.println(parts.length);
        System.out.println(parts[1]);
        System.out.println(String.join(" + ", parts));
    }
}
Вывод
3
груша
яблоко + груша + слива

split делит строку по разделителю и возвращает массив, String.join склеивает массив обратно через заданную строку. Разделитель в split — регулярное выражение (шаблон для поиска текста), а в нём некоторые знаки особые: точка, например, значит «любой символ». Поэтому точку пишут так: split("\\."). Слова, между которыми может быть несколько пробелов, разбивают через split("\\s+") — «один или несколько пробельных символов подряд» (перед этим уберите пробелы по краям через trim()).

Сравнение строк

Строки сравнивают методом equals, а не ==:

Java
import java.util.Scanner;

public class Main {
    public static void main(String[] args) {
        Scanner in = new Scanner(System.in);
        String answer = in.nextLine();
        System.out.println(answer == "yes");
        System.out.println(answer.equals("yes"));
        System.out.println(answer.equalsIgnoreCase("YES"));
    }
}
Ввод
yes
Вывод
false
true
true

== проверяет, один ли это объект в памяти. Строка, прочитанная с клавиатуры, — новый объект, и == даёт false, хотя текст тот же. equals сравнивает текст, equalsIgnoreCase — текст без учёта больших и маленьких букв. Подробно — в справке Сравнение строк: == и equals.

answer "yes" из ввода "yes" в программе "yes" два разных объекта с одинаковым текстом answer == "yes" false один ли это объект? Нет answer.equals("yes") true одинаковый ли текст? Да
Строка "yes" из ввода и строка "yes" из текста программы — два разных объекта с одинаковым текстом: answer == "yes" сравнивает ссылки и даёт false, а answer.equals("yes") сравнивает текст и даёт true.

Для упорядочивания есть a.compareTo(b): отрицательное число, если a идёт раньше b по алфавиту (точнее, по кодам символов), ноль — если строки равны, положительное — если позже.

StringBuilder: когда строку собирают по частям

Каждое s = s + "…" создаёт новую строку и копирует в неё старую. В цикле на тысячи повторов это заметно медленно. Для сборки строки по кусочкам есть StringBuilder — изменяемая строка:

Java
public class Main {
    public static void main(String[] args) {
        StringBuilder sb = new StringBuilder();
        for (int i = 1; i <= 5; i++) {
            sb.append(i).append(' ');
        }
        String result = sb.toString().trim();
        System.out.println(result);
        System.out.println(new StringBuilder("Привет").reverse());
    }
}
Вывод
1 2 3 4 5
тевирП

Частые ошибки

Коротко

Проверьте себя

1. Что вернёт "Москва".substring(1, 3)?
2. Что выведет программа?
Java
String s = "java";
s.toUpperCase();
System.out.println(s);
3. Как правильно проверить, что строка answer равна «да»?
4. Зачем нужен StringBuilder?