Перейти к основному содержимому

Общие операции со строками в Java

· 4 мин. чтения

1. Введение

Строковые значения и операции довольно часто встречаются в повседневной разработке, и любой Java-разработчик должен уметь с ними обращаться.

В этом уроке мы предоставим краткую памятку по общим операциям со строками .

Кроме того, мы прольем свет на различия между equals и «==», а также между StringUtils#isBlank и # isEmpty.

2. Преобразование Char в строку

Символ представляет собой один символ в Java. Но в большинстве случаев нам нужна строка.

Итак, давайте начнем с преобразования char в String s :

String toStringWithConcatenation(final char c) {
return String.valueOf(c);
}

3. Добавление строк

Другой часто необходимой операцией является добавление строк с другими значениями, такими как char :

String appendWithConcatenation(final String prefix, final char c) {
return prefix + c;
}

Мы также можем добавить другие базовые типы с помощью StringBuilder :

String appendWithStringBuilder(final String prefix, final char c) {
return new StringBuilder(prefix).append(c).toString();
}

4. Получение персонажа по индексу

Если нам нужно извлечь один символ из строки, API предоставляет все, что мы хотим:

char getCharacterByIndex(final String text, final int index) {
return text.charAt(index);
}

Поскольку String использует char[] в качестве резервной структуры данных, индекс начинается с нуля .

5. Обработка значений ASCII

Мы можем легко переключаться между char и его числовым представлением (ASCII) с помощью приведения:

int asciiValue(final char character) {
return (int) character;
}

char fromAsciiValue(final int value) {
Assert.isTrue(value >= 0 && value < 65536, "value is not a valid character");
return (char) value;
}

Конечно, поскольку int — это 4 байта без знака, а char — 2 байта без знака, нам нужно убедиться, что мы работаем с допустимыми символьными значениями.

6. Удаление всех пробелов

Иногда нам нужно избавиться от некоторых символов, чаще всего от пробелов. Хороший способ — использовать метод replaceAll с регулярным выражением :

String removeWhiteSpace(final String text) {
return text.replaceAll("\\s+", "");
}

7. Присоединение коллекций к строке

Другой распространенный случай использования — это когда у нас есть какая-то коллекция и мы хотим создать из нее строку:

<T> String fromCollection(final Collection<T> collection) { 
return collection.stream().map(Objects::toString).collect(Collectors.joining(", "));
}

Обратите внимание, что Collectors.joining позволяет указывать префикс или суффикс .

8. Разделение строки

Или, с другой стороны, мы можем разделить строку по разделителю с помощью метода split :

String[] splitByRegExPipe(final String text) {
return text.split("\\|");
}

Опять же, здесь мы используем регулярное выражение, на этот раз для разделения по конвейеру. Поскольку мы хотим использовать специальный символ, мы должны его экранировать .

Другая возможность - использовать класс Pattern :

String[] splitByPatternPipe(final String text) {
return text.split(Pattern.quote("|"));
}

9. Обработка всех символов как потока

В случае детальной обработки мы можем преобразовать строку в IntStream :

IntStream getStream(final String text) {
return text.chars();
}

10. Равенство ссылок и равенство значений

Хотя строки выглядят как примитивный тип, это не так.

Следовательно, мы должны различать равенство ссылок и равенство значений. Равенство ссылок всегда подразумевает равенство значений, но, как правило, не наоборот. Первое мы проверяем с помощью операции '==', а второе — с помощью метода equals :

@Test
public void whenUsingEquals_thenWeCheckForTheSameValue() {
assertTrue("Values are equal", new String("Test").equals("Test"));
}

@Test
public void whenUsingEqualsSign_thenWeCheckForReferenceEquality() {
assertFalse("References are not equal", new String("Test") == "Test");
}

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

@Test
public void whenTheCompileCanBuildUpAString_thenWeGetTheSameReference() {
assertTrue("Literals are concatenated by the compiler", "Test" == "Te"+"st");
}

11. Пустая строка против пустой строки

Между isBlank и isEmpty есть небольшая разница .

Строка считается пустой, если она равна нулю или имеет нулевую длину. Принимая во внимание, что строка пуста, если она равна нулю или содержит только символы пробела:

@Test
public void whenUsingIsEmpty_thenWeCheckForNullorLengthZero() {
assertTrue("null is empty", isEmpty(null));
assertTrue("nothing is empty", isEmpty(""));
assertFalse("whitespace is not empty", isEmpty(" "));
assertFalse("whitespace is not empty", isEmpty("\n"));
assertFalse("whitespace is not empty", isEmpty("\t"));
assertFalse("text is not empty", isEmpty("Anything!"));
}

@Test
public void whenUsingIsBlank_thenWeCheckForNullorOnlyContainingWhitespace() {
assertTrue("null is blank", isBlank(null));
assertTrue("nothing is blank", isBlank(""));
assertTrue("whitespace is blank", isBlank("\t\t \t\n\r"));
assertFalse("test is not blank", isBlank("Anything!"));
}

12. Заключение

Строки являются основным типом во всех видах приложений. В этом руководстве мы изучили некоторые ключевые операции в распространенных сценариях.

Кроме того, мы дали указания на более подробные ссылки.

Наконец, полный код со всеми примерами доступен в нашем репозитории на GitHub .