Рубрики
Без рубрики

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

Автор оригинала: Olivera Popović.

Вступление

Проще говоря, Строка используется для хранения текста, т. е. последовательности символов. Наиболее часто используемым классом Java, без сомнения, является класс String , и при таком высоком использовании разработчикам Java необходимо тщательно ознакомиться с классом и его общими операциями.

Строка

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

Хотя, если вы хотите узнать больше о различных способах создания строк в Java, вам следует проверить String vs StringBuilder vs StringBuffer .

Здесь мы предполагаем, что вы знакомы с тем фактом , что String являются неизменяемыми , поскольку это очень важно знать, прежде чем обращаться с ними. Если нет, обратитесь к ранее связанной статье, где это подробно описано.

Класс String содержит множество вспомогательных методов, которые помогают нам обрабатывать наши текстовые данные:

  • Определить Длину Строки
  • Поиск символов и подстрок
  • Сравнение Строк
  • Извлечение Подстрок
  • Изменение Регистра Строки
  • Удаление Пробелов
  • Форматирование Строк
  • Регулярное выражение и проверка подстрок
  • Замена символов и подстрок
  • Разделение и соединение строк
  • Создание Массивов Символов
  • Равенство Строк

Объединение строк

Прежде чем мы начнем использовать любой из этих методов для строк, мы должны взглянуть на объединение строк, поскольку это довольно распространенная вещь. Давайте начнем с оператора + . Класс String перегружает этот оператор, и он используется для объединения двух строк:

String aplusb = "a" + "b";

// The operands can be String object reference variables as well
String a = "a";
String b = "b";
aplusb = a + b;

Оператор + работает очень медленно. String объекты неизменяемы, поэтому каждый раз, когда мы хотим объединить n строк, Java должна копировать символы из всех строк в новый String объект. Это дает нам квадратичную (O(n^2)) сложность.

Это не проблема с небольшими строками или когда мы объединяем сразу несколько строк одновременно ( Строка + "b" + "c" + "d"; ). Java автоматически использует StringBuilder для объединения нескольких строк одновременно, поэтому источником потери производительности является объединение в циклы. Обычно для чего-то подобного мы использовали бы вышеупомянутый класс StringBuilder .

Он работает как изменяемый |/Строка объект. Это обходит все копирование в конкатенации строк и дает нам линейную (O(n)) сложность.

int n = 1000;

// Not a good idea! Gives the right result, but performs poorly.
String result = "";
for (int i = 0; i < n; i++) {
    result += Integer.valueOf(i);
}

// Better, performance-friendly version.
StringBuilder sb = new StringBuilder("");
for (int i = 0; i < n; i++) {
    sb.append(i);
}

Мы также можем объединить данные с помощью метода concat() :

String str1 = "Hello";
System.out.println(str1.concat("World"));

Выход:

Hello World

Примечание : При использовании конкатенации строк с другими типами данных они неявно преобразуются в их строковое представление:

System.out.println("2 = " + 2); 

Это дает ожидаемый результат”.

System.out.println("2 = " + 1 + 1);

В обычных обстоятельствах, 1+1 сначала будет оцениваться, поскольку Java обрабатывает операции справа налево. Однако на этот раз этого не произойдет – выход есть”. Это происходит из-за так называемого “приоритета оператора”.

По сути, когда встречаются два или более оператора ” + ” (при отсутствии других операторов или скобок), Java начнет с крайнего левого оператора “+” и продолжит оттуда. Если бы мы хотели, чтобы результат снова был”, нам нужно было бы добавить круглые скобки в соответствующем месте.

System.out.println("2 = " + (1 + 1));

С другой стороны, если мы попытаемся использовать метод concat() с другим типом данных:

String str1 = "Hello";
System.out.println(str1.concat(53));

Нас встретили бы с исключением:

incompatible types: int cannot be converted to String

При использовании операнда + Java автоматически преобразует тип данных в строку, тогда как при использовании метода concat () этого не происходит.

Кстати, со всеми методами, которые мы рассмотрим в этой статье, нам не нужно указывать ссылочную переменную, иногда для краткости проще просто использовать их в литерале:

// Instead of this...
String ourString = "this is just some string";
System.out.println(ourString.substring(5,10));

// ...we can do this:
System.out.println("this is just some string".substring(5,10));

На самом деле, любой из способов хорош, но второй способ дает меньше кода.

Определить Длину Строки

length() возвращает общее количество символов в нашей строке .

isEmpty() возвращает true или false в зависимости от того, является ли наша Строка пустой или нет. Таким образом, это означает, что isEmpty() возвращает true для того же случая, что length() возвращает 0.

Например:

if (s.length() == 0) // or s.isEmpty() {
    System.out.println("s is empty");
}
else System.out.println("s isn't empty, it's: " + s + "\n");

Здесь мы покажем, как вы можете использовать эти методы для проверки наличия пустой строки. Условная проверка также может быть заменена на s.is Пустой() и будет работать точно так же.

Поиск символов и подстрок

Поскольку Строка является неизменяемой последовательностью символов, мы можем спросить, какой символ находится в какой позиции, или найти позицию символа. Индексирование Строки начинается с 0, как мы привыкли с массивами.

charAt(индекс int) возвращает значение символа по заданному индексу.

indexOf() перегружен и, следовательно, имеет несколько применений:

  • indexOf(int ch) возвращает первую позицию индекса, соответствующую заданному значению символа
  • indexOf(int ch, int fromIndex) возвращает первый индекс, соответствующий заданному значению символа ПОСЛЕ fromIndex
  • indexOf(строковая подстрока) возвращает (первую) начальную позицию подстроки в Строке объекте, для которого она была вызвана
  • indexOf(строковая подстрока, int fromIndex) такой же, как и в предыдущем методе, но поиск начинается с fromIndex вместо 0

Все перегруженные indexOf() методы возвращают -1 если индекс не был найден.

lastIndexOf() также перегружен и имеет сигнатуры метода, эквивалентные indexOf() , а также возвращает -1, если соответствующий индекс не был найден. Он выполняет поиск объекта String в обратном направлении, если не указан fromIndex .

Индекс, передаваемый методу, должен находиться в диапазоне [0, пример.длина() - 1] должна быть действительной. В противном случае будет выдано исключение StringIndexOutOfBoundsException .

String example = "This should be complicated enough to show some things we should show";

// Find the characters at the indexes given
System.out.println(example.charAt(0));
System.out.println(example.charAt(5));

// An StringIndexOutOfBoundsException is thrown in both these cases:
// System.out.println(example.charAt(-1));
// System.out.println(example.charAt(200));

// Find the index of characters or substrings
System.out.println(example.indexOf('s')); // returns the first occurence of 's'
System.out.println(example.indexOf('s', 4)); // the first 's' after index 4
System.out.println(example.indexOf("should")); // the index of the first "should" in our string
System.out.println(example.indexOf("should", 15)); // the index of the first "should" in our
                                                   // string _after_ index 15

// Find the last index of characters or substrings
System.out.println(example.lastIndexOf('s')); // returns the first occurence of 's' when we look backwards from the end of the string
System.out.println(example.lastIndexOf('s', 45)); // searches for 's' backwards from the position 45
System.out.println(example.lastIndexOf("should")); // returns the position at which the substring 'should' appears, looking backwards from the end of the string
System.out.println(example.lastIndexOf("should", 20)); // finds substring 'should' from position 20 backwards, and returns the position at which it begins

Это приведет к следующему:

T
s
3
5
5
57
64
42
57
5

Примечание : indexOf(int ch, int fromIndex) часто используется в циклах, когда мы хотим что-то сделать для каждого вхождения символа в строке .

int foundAt = -1;
String example = "This should be complicated enough to show some things we should show";
while (true) {
    foundAt = example.indexOf('s', foundAt + 1);
    if (foundAt == -1)
        break;
    else {
        // do something with that information
    }
}

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

Метод compareTo() лексикографически сравнивает нашу Строку с другой. Фактическое сравнение двух строк основано на значении Юникода каждого символа в строке. Метод возвращает либо положительное число, либо отрицательное число, либо 0.

Если бы все символы в нашей строке были строчными (или прописными) буквами, возвращаемое значение метода compareTo() можно было бы интерпретировать как “если бы возвращаемое значение было отрицательным, моя строка стояла бы перед другой строкой в словаре”.

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

Метод compareTo() не просматривает все символы в наших строках, он возвращается, как только достигает конца любой из строк или как только находит несоответствующий символ. В этом случае функция возвращает (значение в Юникоде несоответствующего символа в нашей строке) – (Значение в Юникоде несоответствующего символа в данной строке) .

Для всех, кому интересно – ASCII является частью Unicode. Это означает, что a-z и A-Z находятся в том же порядке, что и в кодировке ASCII, то есть все они следуют друг за другом в соответствующих случаях. А именно, az коды районов между 97-122 и А-Я есть 65-90 . Таким образом, значение для ” a “равно 97, значение для “b” равно 98 и так далее. Таким образом, когда мы вычитаем значение Юникода для ” b ” из “a”, мы получим -1. Это означает, что ” а “- это одна буква перед “в”, как оно и есть.

System.out.println("a".compareTo("a"));
System.out.println("a".compareTo("b"));
System.out.println("1".compareTo("12345678"));
System.out.println("2".compareTo("12345678"));
System.out.println("abcd".compareTo("abgggggggggg"));
0
-1
-7
1
-4

В третьей строке приведенного выше кода в данном случае compareTo возвращает разницу в длине строки, поскольку он не нашел несоответствующего символа до того, как в одной строке “закончились” символы.

И в последней строке мы видим , что -4 печатается из – за " c " - "g" , так как это первое обнаруженное несоответствие, и ему плевать на остальное.

Примечание : “Неожиданная” часть при использовании compareTo() возникает, когда мы сравниваем строки с разными случаями.

System.out.println("ORANGE".compareTo("apple")); 

Мы могли бы ожидать, что метод вернет положительное значение, так как “яблоко” должно стоять перед “АПЕЛЬСИНОМ”. Однако значение Юникода для ” O “меньше, чем значение Юникода для “a”.

Иногда это может быть предпочтительным поведением, но в противном случае мы используем compareToIgnoreCase() . Этот метод делает по существу то же самое , что и по сравнению с () , он просто делает вид, что все в одном и том же случае, и дает нам “правильный” порядок словаря.

Примечание : compareTo() и compareToIgnoreCase() часто используются, когда мы создаем Компаратор для пользовательского класса.

Например, предположим, что у нас есть Человек объект, подобный следующему:

class Person {
    String firstName;
    String lastName;
    // ...
}

Теперь предположим, что у нас есть ArrayList под названием “люди” из многих Человек объектов, в произвольном порядке. Мы хотели бы отсортировать этот ArrayList так, чтобы они были упорядочены в лексикографическом порядке на основе их фамилии, и если у людей одна и та же фамилия, мы хотели бы отсортировать их по имени.

Comparator personComparator = new Comparator() {
    @Override
    public int compare(Person p1, Person p2) {
        if (p1.firstName.compareTo(p2.firstName) != 0) {
            return p1.firstName.compareTo(p2.firstName);
        }
        else return p1.lastName.compareTo(p2.lastName);
    }
};
Collections.sort(people, personComparator);

Извлечение Подстрок

“Подстрока” – это подмножество (или часть) другой строки. Метод substring() возвращает новую строку, которая является подстрокой строки, на которой мы используем метод.

Другими словами, если бы нам нужна была новая строка, содержащая первые три символа нашей строки, мы бы использовали yourstring.substring(0, 3) .

Метод substring() имеет два варианта:

  • подстрока(int startIndex) возвращает Строку , содержащую все символы из startIndex (включительно) до конца нашей Строки . Он ведет себя так же, как подстрока(int startIndex, наша строка.длина()) .
  • подстрока(int startIndex, int endIndex) возвращает Строку , содержащую все символы от startIndex (включительно) до endIndex (эксклюзивно, т. е. символ в endIndex не возвращается)

Примечание : Заданные индексы все еще должны находиться в интервале [0, outstring.длина()-1] . Java, в отличие от некоторых других языков, НЕ поддерживает отрицательные индексы в методе substring () ! Java вызовет исключение StringIndexOutOfBoundsException по любой из следующих причин:

  • startIndex отрицательный
  • endIndex больше длины нашего Строки объекта
  • Начальный индекс больше, чем Конечный индекс

Хотя в документации явно не говорится, что “отрицательные значения вообще не допускаются” (можно иметь привычку указывать -1 в качестве endIndex из других языков программирования), это правило может быть выведено из того факта, что startIndex не может быть отрицательным, и что endIndex должен быть больше, чем startIndex .

Однако Java просто заставляет нас сделать дополнительный шаг по написанию нашей строки.длина() - то же число , что и endIndex вместо просто - Некоторое число .

String ourString = "abcdef";
System.out.println(ourString.substring(0,3));
System.out.println(ourString.substring(2));
System.out.println(ourString.substring(1,3));

// If we want the last few characters
System.out.println(ourString.substring(ourString.length()-3));
abc
cdef
bc
def

Изменение Регистра Строки

Эти два простых метода используются для изменения регистра символов в строке.

  • toLowerCase() : изменяет все прописные символы на строчные (игнорирует все остальное)
  • Прописные буквы() : изменяет все символы нижнего регистра на прописные (игнорирует все остальное)

Git Essentials

Ознакомьтесь с этим практическим руководством по изучению Git, содержащим лучшие практики и принятые в отрасли стандарты. Прекратите гуглить команды Git и на самом деле изучите это!

String ourString = "ThInK oF a ClEvEr StRiNg";

System.out.println(ourString.toLowerCase());
System.out.println(ourString.toUpperCase());
System.out.println(ourString);

Это приведет к следующему:

think of a clever string
THINK OF A CLEVER STRING
ThInK oF a ClEvEr StRiNg

Обратите внимание, что сам начальный String объект не изменился.

Удаление Пробелов

Этот метод возвращает копию исходного объекта String , в котором удалены все начальные и конечные пробелы (пробелы, вкладки, новые строки).

String ourString = "      Any non-leading and non-trailing whitespace is  \n  preserved       ";
System.out.println(ourString.trim());

Выход:

Any non-leading and non-trailing whitespace is  
  preserved

Функция trim() часто используется при обработке пользовательского ввода, так как она гарантирует, что у нас нет бесполезных пробелов, и не изменяет строку, если мы этого не сделаем.

Очень распространенным использованием trim() при вводе пользователем является проверка того, были ли вообще введены какие-либо символы, не являющиеся пробелами:

// Usually we check for empty inputs like this:
if (userinput.isEmpty()) { ... }
// ...or the equivalent
if (userinput.length() != 0) { ... }

// But a better way to check would be this, which
// handles cases where the user entered only
// whitespace (i.e. "    ")
if (userinput.trim().isEmpty()) { ... }

Форматирование Строк

Метод format() возвращает отформатированную строку с заданным форматом и аргументами. Он используется для упрощения жизни при форматировании сложных строк в Java. Он работает аналогично printf в C:

public static String format(String form, Object... args)

Это объявление метода может показаться сложным, но давайте рассмотрим его поближе:

  • Для наших целей часть static означает, что этот метод вызывается через класс String , а не через объект класса String . Это означает, что когда мы хотим использовать этот метод, мы должны написать String.format (...) , а не наш String.format(...) . Мы можем вызвать метод вторым способом, но ваша строка в любом случае не будет играть никакой роли в методе.
  • В ... (три точки) после Объекта просто говорит, что здесь может быть передано переменное число аргументов. Один, два или пятьдесят, все зависит от Строковой формы .

Давайте начнем с простого примера.

int a = 2;
int b = 3;
int c = 4;
int d = 1;

// %d indicates we want to print an integer
System.out.println(String.format("%d", a));
2

Метод format() проходит через строку form , ищет специальные символы и заменяет их аргументами в args .

Специальные символы начинаются с % . В нашем примере мы использовали %d , который Java понимает как “Я попытаюсь проанализировать предоставленный аргумент в args как целое число”.

Немного более проницательный пример того, когда format() полезен:

// Very messy, hard to read, and hard to maintain
System.out.println("a = " + a + "\n" + "b = " + b + "\n" + "c = " + c + "\n" + "d = " + d + "\n");

// Much prettier
System.out.println(String.format("a = %d \nb = %d \nc = %d \nd = %d", a, b, c, d));

Как мы видим в этом примере, Java сопоставляет специальные символы, начинающиеся с % , с аргументами по порядку. Это означает , что когда он увидит первый %d , он сопоставит его с a , вторым %d с b и так далее.

Существует множество специальных символов для формат () , и вы можете найти полный список в документах (включая целую кучу параметров даты/времени), но наиболее часто вы будете видеть и использовать следующие:

  • %d : целочисленные типы (байт, короткий, int, длинный, BigInteger)
  • %s : Строки
  • %f : для с плавающей запятой в виде десятичного числа, %e отформатировано как десятичное число в компьютерной научной нотации, и %g печатает либо то же самое, что %f или %e в зависимости от значения точности после округления.
  • %b : для логических значений. Если значение равно null , выводится “false”

Вообще говоря, метод format() имеет, казалось бы, сложный синтаксис:

%[argument_index$][flags][width][.precision]conversion

argument_index , флаги , ширина и точность являются необязательными , как указано в [] .

Точность может означать разные вещи для разных типов данных. Для поплавков/двойников точность имеет очевидное значение “сколько цифр я должен показать после десятичного периода”. Кроме того, точность определяет максимальное количество символов, которые должны быть записаны в выходные данные.

double ourDouble = 1123.9303;
System.out.println(String.format("%f", ourDouble));
System.out.println(String.format("%.3f", ourDouble)); // specifies that we only want 3 digits after decimal point
System.out.println(String.format("%e", ourDouble));

String ourString  = "what does precision do with strings?";
System.out.println(String.format("%.8s", ourString)); // prints the first 8 characters of our string

int ourInt = 123456789;
// System.out.println(String.format("%.4d", ourInt)); // precision can't be used on ints

Это выведет:

1123.930300
1123.930
1.123930e+03
what doe

Необязательный параметр width указывает минимальную ширину вывода.

// If our number has less than 6 digits, this will
// add extra 0s to the beginning until it does
System.out.println(String.format("%06d", 12)); 

// If our number has more than 6 digits, it will just print it out
System.out.println(String.format("%06d", 1234567));

// We can specify output width, with the output being aligned
// to the right if it's shorter than the given space. If it's
// longer, everything gets printed. The || are added for
// demonstration purposes only
System.out.println(String.format("|%20d|", 12));
// Or we can align the output to the left
System.out.println(String.format("|%-20d|", 12));

// We can also easily print an octal/hexadecimal value of an integer
System.out.println(String.format("Octal: %o, Hex: %x", 10, 10));

Выполнение этого кода приведет к следующему:

000012
1234567
|                  12|
|12                  |
Octal: 12, Hex: a

Регулярное выражение и проверка подстрок

содержит(последовательность символов) возвращает истину , если s является частью нашего String объекта ( s может быть Строкой самой по себе или StringBuilder объектом или действительно чем-либо, что реализует Последовательность символов ), в противном случае он возвращает ложь .

StartsWith(префикс строки) возвращает true , если наш String объект буквально начинается с заданного префикса , в противном случае он возвращает false .

EndsWith(суффикс строки) возвращает true , если наш String объект буквально заканчивается данным суффиксом , в противном случае он возвращает false .

соответствует(регулярное выражение строки) возвращает true , если вся наша Строка соответствует заданному регулярному выражению .

Все эти методы довольно прямолинейны. Хотя соответствует() предполагает знание регулярных выражений.

String ourString = "This string contains a contains.";

System.out.println(ourString.contains("contains"));
System.out.println(ourString.startsWith("T"));
System.out.println(ourString.endsWith(":)"));
System.out.println(ourString.matches(".*string.*"));

Эти операции выводят следующее:

true
true
false
true

Замена символов и подстрок

заменить(char oldChar, char newChar) заменяет все вхождения oldChar на newChar .

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

replaceAll(регулярное выражение строки, замена строки) заменяет все подстроки, соответствующие аргументу regex , строкой replacement .

replaceFirst(регулярное выражение строки, замена строки) заменяет только первую подстроку, соответствующую аргументу regex , строкой replacement .

Чтобы избежать путаницы, replace() также заменяет ВСЕ вхождения последовательности символов, хотя существует метод с именем replaceAll() . Разница в том, что replaceAll() и replaceFirst() используют регулярное выражение для поиска последовательностей символов, которые необходимо заменить.

String ourString = "We really don't like the letter e here";

System.out.println(ourString.replace('e', 'a'));
System.out.println(ourString.replace("here", "there"));
System.out.println(ourString.replaceAll("e(r+)", "a"));
System.out.println(ourString.replaceFirst("e(r+)", "a"));
Wa raally don't lika tha lattar a hara
We really don't like the letter e there
We really don't like the letta e hae
We really don't like the letta e here, only the first occurrence was replaced

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

Методы split() и join() являются двумя сторонами одной медали.

split(регулярное выражение строки) разбивает эту строку с помощью заданного регулярного выражения и возвращает массив символов.

разделение(регулярное выражение строки, ограничение int) аналогично предыдущему методу, но разбивает только ограничение количество раз.

присоединиться(разделитель последовательности символов, последовательность символов... элементы) с другой стороны, возвращает Строку , содержащую все перечисленные элементы , соединенные разделителем .

присоединиться(разделитель последовательности символов, повторяемый расширяет последовательность символов> элементы) это очень сложный способ сказать, что мы можем использовать join() в таких вещах, как списки, для объединения всех элементов в Строку с использованием заданного разделителя . расширяет последовательность символов> элементы)

String ourString = "apples, oranges, pears, pineapples";
String[] fruits = ourString.split(",");

System.out.println(Arrays.toString(fruits));

// This is a great place to use the aforementioned trim() method
// to remove the space at the beginning of some of the words
for(int i = 0; i < fruits.length; i++) {
    fruits[i] = fruits[i].trim();
}

System.out.println(Arrays.toString(fruits)); // Arrays.toString() formats the output array on its own
[apples,  oranges,  pears,  pineapples]
[apples, oranges, pears, pineapples]

Имейте в виду, что split() принимает регулярное выражение, чтобы решить, где разделить строку, поэтому будьте осторожны при использовании символов, которые имеют особое значение в регулярных выражениях.

Поскольку эти символы являются общими (особой проблемой является”.”, поскольку это означает “любой символ” в регулярном выражении), безопасным способом использования split() является Pattern.quote (".") , который гарантирует, что ничто не понимается как специальный символ регулярного выражения.

String ourString = "apples.oranges.pears.pineapples";

// This returns then prints an empty array, since every
// character is interpreted as something to be split at
// and ignored
System.out.println(Arrays.toString(ourString.split(".")));

// The "regex safe" way of doing this would be
System.out.println(Arrays.toString(ourString.split(Pattern.quote("."))));

// Splits our string to two substrings at most,
// completely ignoring all other occurrences of "."
System.out.println(Arrays.toString(ourString.split(Pattern.quote("."), 2))); 
[]
[apples, oranges, pears, pineapples]
[apples, oranges.pears.pineapples]

join() делает прямо противоположное split() . Мы используем join () , когда у нас есть массив/список/и т. Д. Строк (или Stringbuilder / Строковые буферы ), которые мы хотим сформировать в одну новую Строку с использованием некоторого (или без) разделителя.

// A common use is to avoid repetitive concatenation,
// i.e. "1" + "," + "2" + "," + "3" + "," + "4"
System.out.println(String.join(",", "1", "2", "3", "4"));

// We can pass an array or any class that implements
// Iterable (containing character sequences) as the
// second parameter as well
String arrayOfStrings[] = {"1","2","3","4","5"};

System.out.println(String.join("-", arrayOfStrings));
System.out.println(String.join("-", Arrays.asList(arrayOfStrings))); // Works just fine with lists as well

// Join them with an empty string to convert an array
// of Strings to one single String without any extra data
System.out.println(String.join("", arrayOfStrings));
1,2,3,4
1-2-3-4-5
1-2-3-4-5
12345

Создание Массивов Символов

Этот метод преобразует строку , на которой она используется, в массив символов. Он возвращает новый массив символов, содержащий все символы (по порядку), которые находятся в строке |.

toCharArray() простая сигнатура метода.

String ourString = "These will all become separate characters";

System.out.println(Arrays.toString(ourString.toCharArray()));

Это приведет к распечатке следующего:

[T, h, e, s, e,  , w, i, l, l,  , a, l, l,  , b, e, c, o, m, e,  , s, e, p, a, r, a, t, e,  , c, h, a, r, a, c, t, e, r, s]

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

равно(объект str) сравнивает две строки и возвращает true , если строки содержат одинаковые символы в одном и том же порядке, и false в противном случае. Сравнение чувствительно к регистру (используйте equalsIgnoreCase() для сравнения без учета регистра).

Важно понимать, что равно() и == выполняют две разные операции. равно() сравнивает символы внутри Строки объекта, как упоминалось ранее, в то время как == сравнивает равенство ссылок на объекты, чтобы увидеть, ссылаются ли они на один и тот же экземпляр. В то время как такие утверждения, как 1 вернет значение true "строка" может и не вернуться.

Сложность здесь в том, что вывод == зависит от того, как мы инициализировали Строку объекты, которые мы сравниваем:

String s1 = "Just a String";
String s2 = "Just a String";

System.out.println(s1 == s2);
System.out.println(s1.equals(s2));

s2 = new String("Just a String");
System.out.println(s1 == s2);
System.out.println(s1.equals(s2));
true
true
false
true

функция equals() возвращает true в обоих случаях. Поэтому вам всегда следует использовать equals () , если вы действительно не хотите проверить, ссылаются ли две ссылочные переменные на один и тот же экземпляр, хотя это довольно редко.

Вывод

Важно понимать нюансы строк и строковых методов в Java. Тонкие, труднодоступные ошибки могут возникать с такими вещами, как split() и регулярное выражение специальных символов, или при ошибочном использовании == , когда мы хотели использовать equals() .

Лучше всего всегда смотреть на то, как работает метод, проверять их на себе, чтобы помнить о вещах, на которые вам нужно обратить внимание. Кроме того, знание того, какие методы имеются в вашем распоряжении, избавляет вас от ненужной работы по самостоятельному внедрению уже имеющихся методов.