Изучаем java: сравнение строк

Введение в строки. Класс String

Последнее обновление: 31.10.2018

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

Для создания новой строки мы можем использовать один из конструкторов класса String, либо напрямую присвоить строку в двойных кавычках:

public static void main(String[] args) {
        
    String str1 = "Java";
    String str2 = new String(); // пустая строка
    String str3 = new String(new char[] {'h', 'e', 'l', 'l', 'o'});
    String str4 = new String(new char[]{'w', 'e', 'l', 'c', 'o', 'm', 'e'}, 3, 4);//3 -начальный индекс, 4 -кол-во символов
        
    System.out.println(str1); // Java
    System.out.println(str2); //
    System.out.println(str3); // hello
    System.out.println(str4); // come
}

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

Поскольку строка рассматривается как набор символов, то мы можем применить метод length() для нахождения длины строки или длины набора символов:

String str1 = "Java";
System.out.println(str1.length()); // 4

А с помощью метода toCharArray() можно обратно преобразовать строку в массив символов:

String str1 = new String(new char[] {'h', 'e', 'l', 'l', 'o'});
char[] helloArray = str1.toCharArray();

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

String s = "";   // строка не указывает на объект
if(s.length() == 0) System.out.println("String is empty");

В этом случае длина строки, возвращаемая методом length(), равна 0.

Класс String имеет специальный метод, который позволяет проверить строку на пустоту — isEmpty(). Если строка пуста, он возвращает true:

String s = "";   // строка не указывает на объект
if(s.length() == 0) System.out.println("String is empty");

Переменная String может не указывать на какой-либо объект и иметь значение null:

String s = null;   // строка не указывает на объект
if(s == null) System.out.println("String is null");

Значение null не эквивалентно пустой строке. Например, в следующем случае мы столкнемся с ошибкой выполнения:

String s = null;   // строка не указывает на объект
if(s.length()==0) System.out.println("String is empty");	// ! Ошибка

Так как переменная не указывает ни на какой объект String, то соответственно мы не можем обращаться к методам объекта String.
Чтобы избежать подобных ошибок, можно предварительно проверять строку на null:

String s = null;   // строка не указывает на объект
if(s!=null && s.length()==0) System.out.println("String is empty");

Основные методы класса String

Основные операции со строками раскрывается через методы класса String, среди которых можно выделить следующие:

  • concat(): объединяет строки

  • valueOf(): преобразует объект в строковый вид

  • join(): соединяет строки с учетом разделителя

  • сompare(): сравнивает две строки

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

  • getChars(): возвращает группу символов

  • equals(): сравнивает строки с учетом регистра

  • equalsIgnoreCase(): сравнивает строки без учета регистра

  • regionMatches(): сравнивает подстроки в строках

  • indexOf(): находит индекс первого вхождения подстроки в строку

  • lastIndexOf(): находит индекс последнего вхождения подстроки в строку

  • startsWith(): определяет, начинается ли строка с подстроки

  • endsWith(): определяет, заканчивается ли строка на определенную подстроку

  • replace(): заменяет в строке одну подстроку на другую

  • trim(): удаляет начальные и конечные пробелы

  • substring(): возвращает подстроку, начиная с определенного индекса до конца или до определенного индекса

  • toLowerCase(): переводит все символы строки в нижний регистр

  • toUpperCase(): переводит все символы строки в верхний регистр

Разберем работу этих методов.

НазадВперед

Конкатенация — склеивание строк

Есть очень интересная и простая вещь, которую можно делать со строками в Java — их можно склеивать. Такая операция называется конкатенация. Ну или чтобы легче запомнилось — Кон-Котэ-Нация. Хотя часто ее называют «склеивание строк» или даже просто «сложение строк».

Чтобы склеить две строки, нужно использовать знак . Это очень просто:

Конкатенация двух строк

Примеры:

Команда Примечание
содержит строку
содержит строку
содержит строку

Ну и, конечно, одновременно можно складывать много строк, а также складывать строки и переменные.

Примеры:

Команда Примечание
содержит строку содержит строку содержит строку

В последнем примере видно, что текст в переменной  плохо читается, т.к. в нем не хватает пробелов. Чтобы задать один пробел или несколько, нужно просто написать их в коде и обернуть в двойные кавычки. Это проще, чем кажется:

Строка, содержащая один пробел

Кстати, если между кавычками совсем не оставить места (написать две двойные кавычки подряд), получится так называемая «пустая строка»:

Пустая строка

С одной стороны, она вроде бы и есть, а с другой, при ее выводе на экран ничего не выводится. И при склейке с другими строками ничего не происходит. Эдакий аналог нуля, только для строк.

Creating strings using the new keyword

So far we have created strings like primitive types in Java.

Since strings in Java are objects, we can create strings using the keyword as well. For example,

In the above example, we have created a string name using the keyword.

Here, when we create a string object, the constructor is invoked. To learn more about constructor, visit Java Constructor.

Note: The class provides various other constructors to create strings. To learn more, visit Java String (official Java documentation).

Create String using literals vs new keyword

Now that we know how strings are created using string literals and the keyword, let’s see what is the major difference between them.

In Java, the JVM maintains a string pool to store all of its strings inside the memory. The string pool helps in reusing the strings.

While creating strings using string literals, the value of the string is directly provided. Hence, the compiler first checks the string pool to see if the string already exists.

  • If the string already exists, the new string is not created. Instead, the new reference points to the existing string.
  • If the string doesn’t exist, the new string is created.

However, while creating strings using the new keyword, the value of the string is not directly provided. Hence the new string is created all the time.

Где нужны логические операторы

Если коротко, то в условных выражениях, которые могут включать в себя и операторы сравнения (<, >, <=, >=, ==, !=). При вычислении они возвращают значение булева типа.

Условные выражения, в свою очередь, применяются в операторах ветвления (if-else, switch, тернарном). Подробнее об этих операторах тут.

Как применять

Допустим, мы хотим проверить, что значение переменной a больше значений в переменных b и c. То есть сравнить операнд a с двумя другими. Нам поможет логический оператор && (И).

Логический оператор && (И) возвращает true, если слева и справа от него стоят значения true, а иначе — false.

Иными словами, если оба логических высказывания истинны, то и операция && (И) возвращает истину.

Первый пример

Как вычисляется значение выражения (a > b) && (a > c):

Сначала проверяется условие (a > b). Оно вернёт true, так как 6 больше 4. Далее проверяется условие (a > c), которое также вернёт true, ведь 6 больше 3.

Теперь у нас с двух сторон от логического оператора && стоят значения true.

По определению выше или по таблице ещё выше, результат вычисления логического выражения (true && true) равен true.

Второй пример

Результат операции (a > b) вернёт true, так как 6 больше 4, а операция (a > c) уже вернёт false, так как 6 не больше 7.

Значит, слева от логического оператора && стоит true, а справа — false. Следовательно, результат вычисления логического выражения (мы присвоили его булевой переменной d) будет false.

Третий пример

Результат операции сравнения (a > b) равен false, а что вернёт операция (a > c), уже значения не имеет (смотрите определение выше) — результат вычисления логического выражения (мы присвоили его булевой переменной d) будет равен false.

Creating Format Strings

You have printf() and format() methods to print output with formatted numbers. The String class has an equivalent class method, format(), that returns a String object rather than a PrintStream object.

Using String’s static format() method allows you to create a formatted string that you can reuse, as opposed to a one-time print statement. For example, instead of −

Example

System.out.printf("The value of the float variable is " +
                  "%f, while the value of the integer " +
                  "variable is %d, and the string " +
                  "is %s", floatVar, intVar, stringVar);

You can write −

String fs;
fs = String.format("The value of the float variable is " +
                   "%f, while the value of the integer " +
                   "variable is %d, and the string " +
                   "is %s", floatVar, intVar, stringVar);
System.out.println(fs);

Как отсортировать список строк по их длине в Java 7 и 8

Ниже приведен пример использования этого компаратора длины строк для сортировки списка строк по их длине. В этом примере мы продемонстрировали программы на JDK 6 и 7 с использованием анонимного класса, и новый способ с использованием лямбда-выражений, который доступен в Java 8. Он занимает всего одну строку и его намного проще понять, если вы знакомы с синтаксисом лямбда-выражений.

Как отсортировать список строк по их длине в Java 7 и 8

Java 6, 7

Import java.util.ArrayList;
Import java.util.Arrays;
Import java.util.Collections;
Import java.util.Comparator;
Import java.util.List;

/ *
 * Программа Java для сортировки списка строк по их длине
 * /

public class StringComparisonByLength{

  Public static void main (String [] args) {

List<String> books = new ArrayList<>(Arrays.asList("Effective Java", "Algorithms", "Refactoring" ));
System.out.println("Sorting List of String by length in JDK 7 ======");
System.out.println("The original list without sorting");
System.out.println(books);

    Comparator<String> byLength = new Comparator<String>(){
      @Override
      Public int compare (String s1, String s2) {
        Return s1.length () - s2.length ();
        }
    };

    Collections.sort(books, byLength);
    System.out.println("The same list after sorting string by length");

    System.out.println(books);
  }
}

Результат

Sorting List of String by length in JDK 7 ======
The original list without sorting 
The same list after sorting string by length

Java 8

Import java.util.ArrayList;
Import java.util.Arrays;
Import java.util.Comparator;
Import java.util.List;
/ *
 * Программа Java для сортировки списка строк по их длине в JDK 8
 * /

public class SortingListOfStringByLength{

  public static void main(String[] args) {

    // В Java 8
    System.out.println("Sorting List of String by length in Java 8 ======");

   List<String> cities = new ArrayList<>(Arrays.asList("London", "Tokyo", "NewYork"));
    System.out.println("The original list without sorting");
    System.out.println(cities);

    cities.sort((first, second) -> Integer.compare(first.length(), second.length()));

    System.out.println("The same list after sorting string by length");
    System.out.println(cities);
  }
}

Результат

Sorting List of String by length in Java 8 ====== 
The original list without sorting 
 
The same list after sorting string by length 

Это все, что касается сравнения длины строк Java и сортировки списка String по длине в Java 7 и Java 8. В последней версии языка делать это намного удобнее, поскольку можно создать пользовательский компаратор только одной строкой, используя лямбда-выражение. API JDK 8 содержит множество подобных методов, которые облегчают еще более сложные сравнения. Например, используя метод thenComparing(), можно связать несколько компараторов.

Данная публикация является переводом статьи «How to compare String by their length in Java 7 and 8» , подготовленная редакцией проекта.

Методы класса String

У класса очень много методов: одних только конструкторов у него 18 штук! Поэтому ниже мы приведем только самые основные из них:

Методы Описание
Возвращает количество символов в строке
Проверяет, что строка == пустая строка
Проверяет, что в строке — только whitespace-символы: пробел, tab, enter и т.п.
Возвращает символ, который стоит на index-позиции в строке.
Возвращает массив символов (копию), из которых состоит строка
Преобразует строку в набор байт и возвращает массив байт.
Разделяет строку на несколько подстрок.
Склеивает вместе несколько подстрок
Помещает строку в пул .

Больше о конструкторах вы можете узнать из статьи Зачем нужен конструктор?

Давайте напишем программу, которая преобразовывает путь к файлу из Unix Style в Windows Style. Unix в качестве разделителя директорий использует символ , Windows — символ .

Решение 1 — использование массива char’ов

Код Примечания
Создание объекта Scanner
Чтение строки с консоли
Преобразование строки в массив символов
Цикл по символам
Если символ равен ,
заменить его на . Не забываем про экранирование.
Создаем новую строку на основе массива символов.
Выводим строку на экран.

Решение 2 — использование методов и :

Код Примечания
Создание объекта Scanner
Чтение строки с консоли
Преобразование строки в массив строк. В качестве разделителя используется символ (дополнительные два слеша – это следствие двойного экранирования).
Объединяем все строки из массива строк, в качестве разделителя используется символ (мы видим его экранированным).
Выводим строку на экран.

Решение 3 — использование метода :

Код Примечания
Создание объекта Scanner
Чтение строки с консоли
Просто заменяем один символ на второй
(второй — экранирован)
Выводим строку на экран.

Поиск в строке в Java

Чтобы найти индекс первого вхождения подстроки в строку, используют метод indexOf(), последнего — метод lastIndexOf(). Если подстрока не найдена, оба метода вернут -1:

String str = "Hello world";
int index1 = str.indexOf('l'); // 2
int index2 = str.indexOf("wo"); //6
int index3 = str.lastIndexOf('l'); //9

Чтобы определить, начинается строка с определённой подстроки, применяют метод startsWith(). Что касается метода endsWith(), то он даёт возможность определить оканчивается ли строка на определенную подстроку:

String str = "myfile.exe";
boolean start = str.startsWith("my"); //true
boolean end = str.endsWith("exe"); //true

compareTo()

Метод compareTo() сравнивает строку с другой и возвращает int, сообщающий, меньше ли эта строка, равна или больше другой.

  • Если строка в порядке сортировки раньше, чем другая, возвращается отрицательное число.
  • совпадает с другой, возвращается 0.
  • Если находится после другой в порядке сортировки, выводит положительное число.

Вот пример:

String one   = "abc";
String two   = "def";
String three = "abd";

System.out.println( one.compareTo(two)   );
System.out.println( one.compareTo(three) );

В этом примере сравнивается одна строка с двумя другими. Вывод:

-3
-1

Числа отрицательны, потому что одна строка находится в порядке сортировки раньше, чем две другие.

Метод compareTo() фактически принадлежит интерфейсу Comparable.

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

И еще один интересный метод класса String — .

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

Код Вывод на экран

Скорее всего, ваш код будет выглядеть примерно так:

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

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

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

Не очень читаемо, не так ли?

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

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

Пример:

Код Результат

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

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

Код Результат
будет равна

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

Символ Обозначение
целое число: , , ,
вещественное число: ,
Символ

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

Код Результат
будет равна

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

Список примитивных типов

В Java есть 8 базовых примитивных типов. Примитивными их называют потому, что значения этих типов не являются объектами и хранятся прямо внутри переменных.

Вот таблица, которая содержит краткую информацию по этим типам:

Тип Размер,
байт
Диапазон значений Значение по умолчанию Описание
1 -128 .. 127 Самое маленькое целое — один байт
2 -32,768 .. 32,767 Короткое целое, два байта
4 -2*109 .. 2*109 Целое число, 4 байта
8 -9*1018 .. 9*1018 Длинное целое, 8 байт
4 -1038 .. 1038 Дробное, 4 байта
8 -10308 .. 10308 Дробное, двойной длины, 8 байт
1 , Логический тип (только & )
2 0 .. 65,535 Символы, 2 байта, все больше 0

Значение по умолчанию

Кстати, важный нюанс. Если вы объявили переменную-класса (поле класса) или статическую переменную-класса, и не присвоили ей никакого значения, она инициализируется значением по умолчанию. Список таких значений приведен в таблице.

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

Но давайте вернемся к примитивным типам и рассмотрим их подробнее

Java string методы — использование оператора ==

Оператор == проверяет ссылки, а не значения. Это означает, что он проверяет, являются ли сравниваемые элементы одним и тем же объектом. Если две переменные String указывают на один и тот же объект в памяти, сравнение возвращает true. В противном случае — false:

"Java" == "Java" //true

Здесь литералы интернируются компилятором и таким образом ссылаются на один и тот же объект:

new String("Java") == "Java" // false

Приведенные выше переменные String указывают на разные объекты:

new String("Java") == new String("Java") // false

Приведенные выше переменные String также указывают на разные объекты.

Оператор ‘==’ не сравнивает строки в java, а только ссылки, на которые они строки.

Пример

class TestClass{
  public static void main (String[] args){
    // ссылается на один и тот же объект, возвращает true
    if(  "Java" == "Java" ){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
    // указывает на другой объект, возвращает false
    if(new String("Java") == "Java"){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
    // указывает на другой объект, возвращает false
    if(new String("Java") == new String("Java") ){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
  }
}

Результат

Statement  is true
Statement is false
Statement is false

Pad a String Using Libraries

And, there are external libraries that already offer padding functionalities.

3.1. Apache Commons Lang

Apache Commons Lang provides a package of Java utility classes. One of the most popular ones is the StringUtils.

To use it, we’ll need to include it into our project by adding to our pom.xml file:

And then we pass the inputString and the length, just like the methods we created. We can also pass the padding character:

Again, the String will be padded with spaces by default or we need to explicitly set another pad character.

There are also corresponding rightPad() methods.

To explore more features of the Apache Commons Lang 3, you can check out our introductory tutorial. If you would like to see other ways of the String manipulation using the StringUtils class, please refer to this article.

3.2. Google Guava

Another library that we can use is Google’s Guava. Of course, we first need to add it to the project by adding :

And then use the Strings class:

There is no default pad character in this method, so we need to pass it every time.

To right pad, we can use padEnd() method.

The Guava library offers much more features and we have covered a lot of them. You can look here for the Guava related articles.

Метод String equals()

В Java сравнение строк equals проверяет исходное содержимое строки. Он возвращает true, если параметр — это объект String, который представляет собой ту же строку символов, что и объект:

Objects.equals("Java", new String("Java")) //true

Если нужно проверить, имеют ли две строки одинаковое значение, можно использовать Objects.equals().

Пример

class TestClass{
  public static void main (String[] args)	{
    String str1 = "Java";
    String str2 = "Java";
    String str3 = "ASP";
    String str4 = "JAVA";
    String str5 = new String("Java");
    // оба равны, возвращают true
    if(str1.equals(str2)){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
    // оба не равны, возвращают false
    if(str1.equals(str3)){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
    // оба не равны, возвращают false
    if(str1.equals(str4)){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
    // оба равны, возвращают true
    if(str1.equals(str5)){
      System.out.println("Statement  is true");
    }else{
      System.out.println("Statement is false");
    }
  }
}

Результат

Statement  is true
Statement is false
Statement is false
Statement  is true

Подстроки

Вы можете извлечь часть строки – подстроку с помощью метода substring() класса String:

String string1 = "Hello World";

String substring = string1.substring(0,5);

После выполнения этого кода переменная substring будет содержать строку Hello.

Метод substring() принимает два параметра. Первый – это индекс символа первого символа, который будет включен в подстроку. Второй – это индекс последнего символа для включения в подстроку. Параметры означают «от – в том числе до -».

Первый символ в строке имеет индекс 0, второй символ имеет индекс 1 и т. д. Последний символ в строке имеет индекс String.length() – 1.

Что нужно помнить о строках

Строки не изменяемые, поэтому состояние строки изменить нельзя.

Для экономии памяти JVM хранит строки в пуле строк. При создании новой строки JVM проверяет ее значение и указывает на существующий объект. Если в пуле нет строки с этим значением, то JVM создаёт новую строку.

Оператор » == » сравнивает ссылки на объект. Метод equals() сравнивает значения строк. То же правило будет применяться ко всем объектам.

При использовании оператора new будет создана новая строка в хипе (Прим. переводчика — в оригинале написано, что в пуле, но это не так, спасибо zagayevskiy), даже если есть строка с тем же значением.

Конвертировать с использованием StringBuffer или StringBuilder

StringBuilder и StringBuffer – это классы, используемые для объединения нескольких значений в одну строку. StringBuffer является потокобезопасным, но медленным, тогда как StringBuilder не является поточно-ориентированным, но работает быстрее.

Пример 1

class Method5
{
  public static void main(String args[]) 
  { 
    int number1 = -1234;
    StringBuilder sb = new StringBuilder(); 
    sb.append(number1); 
    String str1 = sb.toString(); 
    System.out.println("With StringBuilder method: string = " + str1); 
    StringBuffer SB = new StringBuffer(); 
    SB.append(number1); 
    String str2 = SB.toString(); 
    System.out.println("With StringBuffer method: string = " + str2); 
  } 
}

Вывод

With StringBuilder method: string = -1234
With StringBuffer method: string = -1234

Объект StringBuilder представляет объект String, который можно изменять и обрабатывать как массив с последовательностью символов. Чтобы добавить новый аргумент в конец строки, экземпляр StringBuilder реализует метод append().

Пример 2

class Method6
{
  public static void main(String args[]) 
  { 
	String str1 = new StringBuilder().append(1234).toString(); 
    System.out.println("With StringBuilder method: string = " + str1); 
    String str2 = new StringBuffer().append(1234).toString(); 
    System.out.println("With StringBuffer method: string = " + str2); 
  } 
}

Вывод

With StringBuilder method: string = -1234
With StringBuffer method: string = -1234

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

Что сейчас произошло? Понимание поведения String

В первой строке мы видим:

В этом случае результат false , потому что, когда метод trim() удаляет пробелы он создаёт новый String с помощью оператора new .

Здесь нет никакой тайны, строки одинаковы в пуле строк. Это сравнение возвращает true .

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

Поскольку мы использовали метод equals() , будет сравниваться значение строки, а не экземпляр объекта.

В этом случае, не имеет значение разные объекты или нет, поскольку сравнивается значение. Результат true .

Окончательно, мы имеем:

Как вы видели ранее, метод intern() помещает строку в пул строк. Обе строки указывают на один и тот же объект, поэтому в этом случае true .

Split

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

String text = "OTUS is a good company";
String[] words = text.split(" ");
for(String word  words){
    System.out.println(word);
}

В нашем случае строка разделится по пробелу, и мы получим следующий консольный вывод:

OTUS
is
a
good
company

Вот и всё! Узнать больше всегда можно на наших курсах:

При написании статьи использовались материалы:
1. «Java-примеры: найти последнее вхождение подстроки в строке».
2. «Основные операции со строками».

Добавить комментарий

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

Adblock
detector