JavaRush /Курсы /Java Syntax New Beta /Вспомогательные классы для работы со строками в Java

Вспомогательные классы для работы со строками в Java

Java Syntax New Beta
9 уровень , 6 лекция
Открыта

— Привет, Амиго. Сегодня мы разберем ещё несколько самых частых сценариев работы со строками. Например, ты знаешь, как разбить строку на несколько частей?

— Сходу не скажу, Элли. Но ты ведь расскажешь?

Метод split()

— Для этого есть несколько способов. Первый способ разбить строку на несколько частей — использовать метод split(). В него в качестве параметра нужно передать регулярное выражение: специальный шаблон строки-разделителя. Что такое регулярное выражение, вы узнаете в квесте Java Collections.

Пример:

Код Результат
String str = "Good news everyone!";
String[] strings = str.split("ne");
System.out.println(Arrays.toString(strings));
Результатом будет массив из трех строк:
["Good ", "ws everyo", "!"]

Просто, но иногда такой подход избыточен. Если разделителей много, например, «пробел», «enter», «таб», «точка», приходится конструировать достаточно сложное регулярное выражение.

— Ну да. А если сложно читать, значит, сложно вносить изменения.

Класс StringTokenizer

— В Java есть специальный класс, вся работа которого — разделять строку на подстроки.

— Этот класс не использует регулярные выражения: вместо этого в него просто передается строка, состоящая из символов-разделителей. Преимущества этого подхода в том, что он не разбивает сразу всю строку на кусочки, а потихоньку идет от начала к концу.

Класс состоит из конструктора и двух методов. В конструктор нужно передать строку, которую мы разбиваем на части, и строку — набор символов, используемых для разделения.

Методы Описание
String nextToken()
Возвращает следующую подстроку
boolean hasMoreTokens()
Проверяет, есть ли еще подстроки.

— Этот класс мне чем-то напомнил класс Scanner, у которого тоже были методы nextLine() и hasNextLine().

— Хорошая ассоциация. Создать объект StringTokenizer можно командой:

StringTokenizer имя = new StringTokenizer(строка, разделители);

Где строка — это строка, которую будем делить на части. А разделители — это строка, каждый символ которой считается символом-разделителем. Пример:

Код Вывод на экран
String str = "Good news everyone!";

StringTokenizer tokenizer = new StringTokenizer(str,"ne");
while (tokenizer.hasMoreTokens())
{
   String token = tokenizer.nextToken();
   System.out.println(token);
}
Good 
ws 
v
ryo
!

— Обрати внимание, что разделителем считается каждый символ строки, переданный второй строкой в конструктор StringTokenizer.

9
Задача
Java Syntax Pro, 9 уровень, 6 лекция
Недоступна
Степень двойки
Реализуй метод getPowerOfTwo(int power), который возвращает число 2 в степени power. Тебе нужно изменить реализацию метода getPowerOfTwo(int), используя соответствующий побитовый сдвиг.

Метод String.format() и класс StringFormatter

— Ещё один интересный метод класса String — format().

— Допустим, у тебя есть различные переменные с данными. Как вывести их на экран одной строкой? Например, у нас есть данные (левая колонка) и желаемый вывод (правая колонка):

Код Вывод на экран
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;
User = {name: Amigo, age: 12 years, friend: Diego, weight: 200 kg.}

Код такой программы будет выглядеть примерно так:

Код программы
String name = "Amigo";
int age = 12;
String friend = "Diego";
int weight = 200;

System.out.println("User = {name: " + name + ", age:" + age + " years, friend: " + friend+", weight: " + weight + " kg.}");

— Согласись, код не слишком читабельный. Более того, если бы имена переменных были длиннее, код стал бы еще сложнее:

Код программы

class User {
    ......
    public String getName() {
        return name;
    }

    public int getAge() {
        return age;
    }

    public List getFriends() {
        return friends;
    }

    public ExtraInformation getExtraInformation() {
        return extraInformation;
    }
}

User user = new User();

System.out.println("User = {name: " + user.getName() + ", age:" + user.getAge() + " years, friend: " + user.getFriends().get(0) + ", weight: " + user.getExtraInformation().getWeight() + " kg.}");

— Да, читается так себе!

— Не переживай, в реальных программах такая ситуация встречается часто, поэтому я хочу рассказать о способе, как проще и короче записать этот код.

String.format

— У класса String есть статический метод format(): он позволяет задать шаблон объединения строки с данными. Общий вид этой команды такой:

String имя = String.format(шаблон, параметры);

Пример:

Код Результат
String.format("Age=%d, Name=%s", age, name);
Age=12, Name=Amigo
String.format("Width=%d, Height=%d", width, height);
Width=20, Height=10
String.format("Fullname=%s", name);
Fullname=Diego

— В метод format() первым параметром передают строку-шаблон, которая содержит весь нужный текст, а в местах, где нужно вставлять данные, написаны специальные символы типа %d, %s и т.п.

— Вот эти %s и %d метод format() и заменяют на параметры, которые идут следом за строкой-шаблоном. Если нужно подставить строку, мы пишем %s, если число — %d. Пример:

Код Результат
String s = String.format("a=%d, b=%d, c=%d", 1, 4, 3);
s будет равна "a=1, b=4, c=3"

— Вот краткий список параметров, которые можно использовать внутри шаблона:

Символ Обозначение
%s
String
%d
целое число: byte, short, int, long
%f
вещественное число: float, double
%b
boolean
%c
char
%t
Date
%%
Символ %

— Эти параметры указывают на тип данных, но есть еще параметры, которые указывают на порядок данных. Чтобы взять параметр по его номеру (нумерация начинается с единицы), нужно записать «%1$d» вместо «%d». Пример:

Код Результат
String s = String.format("a=%3$d, b=%2$d, c=%d", 11, 12, 13);
s будет равна "a=13, b=12, c=11"

%3$d возьмет 3-й параметр-переменную, %2$d возьмет второй параметр. %d возьмет самый первый параметр-переменную. Параметры шаблона %s, %d обращаются к переменным-параметрам независимо от параметров шаблона типа %3$d или %2$s

9
Задача
Java Syntax Pro, 9 уровень, 6 лекция
Недоступна
Флаги
Реализуй методы: 1. setFlag(int number, int flagPos) - устанавливает значение "1" биту под индексом flagPos числа number и возвращает новое значение. 2. resetFlag(int number, int flagPos) - устанавливает значение "0" биту под индексом flagPos числа number и возвращает новое значение. 3. checkFlag(in

String Pool

Фрагмент лекции JavaRush - университета.


— Все строки, которые были заданы в коде в виде литералов, во время работы программы хранятся в памяти в так называемом StringPool. StringPool — это специальный массив для хранения строк. Цель его создания — оптимизация хранения строк:

— Во-первых, строки, заданные в коде, нужно все-таки где-то хранить. Код — это команды, а данные (тем более такие большие как строки) нужно хранить в памяти отдельно от кода. В коде фигурируют только ссылки на объекты-строки.

— Во-вторых, все одинаковые литералы можно хранить в памяти только один раз. Так оно и работает. Когда код твоего класса загружается Java-машиной, все строковые литералы добавляются в StringPool, если их там еще нет. Если уже есть, просто используется ссылка на строку из StringPool.

Поэтому если в своем коде ты присвоишь нескольким String-переменным одинаковые литералы, переменные будут содержать одинаковые ссылки. В StringPool литерал будет добавлен только один раз, во всех остальных случаях будет браться ссылка на уже загруженную в StringPool строку.

Как это примерно работает:

Код Работа с StringPool
String a = "Привет";
String b = "Привет";
String c = "Пока";
String[] pool = {"Привет", "Пока"};
a = pool[0];
b = pool[0];
c = pool[1];

— Именно поэтому переменные a и b будут хранить одинаковые ссылки.

— Надеюсь, понял всё правильно.

Метод intern().

— Ну и самое интересное: ты можешь программно добавить любую строку в StringPool. Для этого нужно просто вызвать метод intern() у String-переменной.

— Метод intern() добавит строку в StringPool, если ее еще там нет, и вернет ссылку на строку из StringPool.

— А что будет, если в StringPool добавить с помощью метода intern() две идентичные строки?

— Метод вернет одинаковые ссылки. Это можно использовать чтобы сравнивать строки по ссылке. Пример:

Код Примечание
String a = new String("Привет");
String b = new String("Привет");
System.out.println(a == b);


false
String a = new String("Привет");
String b = new String("Привет");

String t1 = a.intern();
String t2 = b.intern();
System.out.println(a == b);
System.out.println(t1 == t2);





false
true

Вряд ли ты будешь часто пользоваться этим методом. Однако о нем любят спрашивать на собеседованиях.

— Поэтому лучше о нем знать, чем не знать. Спасибо, Элли!

Комментарии (38)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Fanis Уровень 15
25 августа 2023
Ребята, такой вопрос: Если в 1-ый String введем какую то строку, но потом создаем 2-ой String с такой же строкой они оба оказываются в "Srting pool" и оба ссылаются на одну строку. Затем если изменить 1ый String, то строка в "Srting pool" изменится и значение 2-ой строки тоже изменится? или так как на одну строку ссылаются 2 стринга то при изменении первого создастся копия и 2-ой String не меняется?
Larandvik Уровень 30
1 февраля 2023
Разработчики, поправьте пожалуйста условие задачи: {"java", "util", "stream"} потому что правильное решение: [java, util, stream]
Anonymous #3285075 Уровень 29
30 апреля 2023
Дебилизм какой-то, понять не могу как это решать:(
Larandvik Уровень 30
2 мая 2023
Как многие говорят, это нормальное состояние в процессе обучения. Главное не останавливаться. Читай все статьи которые дают. Читай так же книги или Шилдта или Хорстмана. Гугли вопросы, которые не понятно, многое хорошо описано на хабре. Сейчас тебе здесь что-то не понятно. Через пару недель ты не будешь понимать что-то дальше. Главное продолжай
Anonymous #3285075 Уровень 29
2 мая 2023
Спасибо)
Александр Уровень 10
15 января 2023
Как же сложно у меня идет все, что связано со строками..
Nixis Уровень 10
17 декабря 2022
Упоминается некий класс StringFormatter. Кто-нибудь нашел его описание?
Lo Уровень 35 Expert
29 марта 2023
Да-да, забыли про него написать. Может в видео о нем было, я его не смотрела, т.к. не нравится, как объясняет конкретно этот препод. Удивительно,что про этот класс даже в общем поиске мало что есть, только краткое описание по типу официальной документации. Конкретных примеров применения не нашла.
Никита Уровень 11
29 августа 2022
Разобраться со стрингпулом помогла данная статья с джавараша: https://javarush.com/groups/posts/equals-java-sravnenie-strok?post=full#discussion
Никита Уровень 11
28 августа 2022
Странно, что при указании порядка данных в String.format() отсчёт параметров ведётся не с нуля, а с единицы.
Lo Уровень 35 Expert
29 марта 2023
похоже это единственный случай!😬
Grock Уровень 44
27 июля 2022
Немного сбило с толку утверждение в лекции: Класс StringTokenizer ... Класс состоит из конструктора и двух методов. По факту же в классе 3 конструктора и 6 методов (см. здесь).
Qunjavi Уровень 10
12 августа 2022
Спасибо за ссылку, но на практике все же описанных методов/конструкторов достаточно, и это не сбивает с толку, а скорее наоборот.
Oleg #2857544 Уровень 13
15 июня 2022
В лекции Амиго упомянул про класс Scanner и два его метода nextLine() и hasNextLine(). Как будто в предыдущих лекциях это разбирали. Но я помню этого не было, кроме того в начальных лекциях сказали что сканнером лучше не пользоваться, вместо этого используйте BufferedReader.
Алексей Кобзев Уровень 37
16 июня 2022
Но затем было две или три задачи, в которых был импортирован именно сканнер, так что если решать все задачи без исключения, то к этому моменту сканнер ты использовал минимум дважды. Правда метод hasNextLine() там был не нужен) Курс, судя по всему, меняется со временем, и в прошлых версиях сканнер использовался чаще, чем в новой, а потому иногда такое проскакивает. Все равно полезно разобраться)
Mars Уровень 20
28 апреля 2022
Всем привет! Банальная проблема кодировок! Помогите. ничего не помогает. UTF 8 поставить в настройках, внизу справа, прописать где-то там в коде.. не помогло. Прошу выручить)
Зепп Бранниган Уровень 41 Moderator
29 апреля 2022
У Вас JDK 18? Обратитесь к нам в ЛС.
NextGenSeafarer Уровень 1
5 мая 2022
Мне помогло вот так: Settings - File Encodings - "Project encoding" (меняй на windows 1251) Global encoding : "System default UTF-8" + может помочь смена региона на компьютере на Россию + язык стандартный русский + в IDEA в терминале (Alt + F12) введи команду : " chcp 65001 " - смена кодировки на UTF-8 там есть стрелка вниз ещё рядом с "+", я там выбирал все терминалы что есть на компьютере и вводил эту команду Удачи!) 🤖🤖🤖
Natalie Уровень 24
13 апреля 2022
Как-то тяжеловато String заходит, непонятно почему(