«1. Введение
Строковые значения и операции довольно часто встречаются в повседневной разработке, и любой Java-разработчик должен уметь с ними обращаться.
В этом уроке мы предоставим краткую памятку по общим операциям со строками.
Кроме того, мы прольем свет на различия между equals и «==» и между StringUtils#isBlank и #isEmpty.
2. Преобразование Char в строку
Char представляет один символ в Java. Но в большинстве случаев нам нужна строка.
Итак, давайте начнем с преобразования символов в строки:
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. Присоединение коллекций к строке
Еще один распространенный вариант использования — когда у нас есть какая-то коллекция и мы хотим создать строку из it:
<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.