it-swarm.com.ru

Как сравнить строки в Java?

До сих пор я использовал оператор == в моей программе для сравнения всех своих строк. Однако я столкнулся с ошибкой, вместо этого изменил одну из них на .equals(), и она исправила ошибку.

== плохо? Когда это должно и не должно быть использовано? Какая разница?

726
Nathan H

== проверяет равенство ссылок (являются ли они одним и тем же объектом).

.equals() проверяет равенство значений (являются ли они логически "равными").

Objects.equals () проверяет null перед вызовом .equals(), поэтому вам не нужно (доступно с JDK7, также доступно в Guava ).

String.contentEquals () сравнивает содержимое String с содержимым любого CharSequence (доступно с Java 1.5).

Следовательно, если вы хотите проверить, имеют ли две строки одинаковые значения, вы, вероятно, захотите использовать Objects.equals().

// These two have the same value
new String("test").equals("test") // --> true 

// ... but they are not the same object
new String("test") == "test" // --> false 

// ... neither are these
new String("test") == new String("test") // --> false 

// ... but these are because literals are interned by 
// the compiler and thus refer to the same object
"test" == "test" // --> true 

// ... string literals are concatenated by the compiler
// and the results are interned.
"test" == "te" + "st" // --> true

// ... but you should really just call Objects.equals()
Objects.equals("test", new String("test")) // --> true
Objects.equals(null, "test") // --> false
Objects.equals(null, null) // --> true

Вы почти всегда хотите использовать Objects.equals(). В редкой ситуации, когда вы знаете , с кем имеете дело - интернированный строки, вы можете использовать ==.

From JLS 3.10.5. Строковые литералы :

Более того, строковый литерал всегда ссылается на один и тот же экземпляр класса String. Это связано с тем, что строковые литералы - или, в более общем случае, строки, являющиеся значениями константных выражений ( §15.28 ) - "интернированы", чтобы обмениваться уникальными экземплярами, используя метод String.intern.

Подобные примеры также можно найти в JLS 3.10.5-1 .

5347
Aaron Maenpaa

== проверяет ссылки на объекты, .equals() проверяет строковые значения.

Иногда это выглядит так, как будто == сравнивает значения, потому что Java выполняет некоторые закулисные действия, чтобы убедиться, что идентичные строки в действительности являются одним и тем же объектом.

Например:

String fooString1 = new String("foo");
String fooString2 = new String("foo");

// Evaluates to false
fooString1 == fooString2;

// Evaluates to true
fooString1.equals(fooString2);

// Evaluates to true, because Java uses the same object
"bar" == "bar";

но остерегайтесь нулей!

== хорошо обрабатывает null строки, но вызов .equals() из пустой строки вызовет исключение:

String nullString1 = null;
String nullString2 = null;

// Evaluates to true
System.out.print(nullString1 == nullString2);

// Throws a NullPointerException
System.out.print(nullString1.equals(nullString2));

Поэтому, если вы знаете, что fooString1 может быть нулевым, сообщите об этом читателю, написав

System.out.print(fooString1 != null && fooString1.equals("bar"));

Ниже короче, но менее очевидно, что он проверяет на ноль (из Java 7):

System.out.print(Objects.equals(fooString1, "bar"));
692
Whatsit

== сравнивает ссылки на объекты.

.equals() сравнивает строковые значения.

Иногда == дает иллюзии сравнения значений String, как в следующих случаях:

String a="Test";
String b="Test";
if(a==b) ===> true

Это связано с тем, что когда вы создаете какой-либо литерал String, JVM сначала ищет этот литерал в пуле String, и, если он найдет совпадение, эта же ссылка будет передана новой строке. Из-за этого мы получаем:

(a == b=> верно) ==

                       String Pool
     b -----------------> "test" <-----------------a

Тем не менее, == терпит неудачу в следующем случае:

String a="test";
String b=new String("test");
if (a==b) ===> false

В этом случае для new String("test") в куче будет создан оператор new String, и эта ссылка будет передана b, поэтому b будет дана ссылка на кучу, а не в пул строк.

Теперь a указывает на строку в пуле строк, а b указывает на строку в куче. Из-за этого мы получаем:

если (a == b=> false.) ==

                String Pool
     "test" <-------------------- a

                   Heap
     "test" <-------------------- b

Хотя .equals() всегда сравнивает значение String, поэтому в обоих случаях оно дает значение true:

String a="Test";
String b="Test";
if(a.equals(b)) ===> true

String a="test";
String b=new String("test");
if(a.equals(b)) ===> true

Поэтому использование .equals() всегда лучше.

425
Ganesh

Оператор == проверяет, являются ли две строки одним и тем же объектом.

Метод .equals() проверит, имеют ли две строки одинаковое значение.

217
Clayton

Строки в Java являются неизменяемыми. Это означает, что всякий раз, когда вы пытаетесь изменить/модифицировать строку, вы получаете новый экземпляр. Вы не можете изменить исходную строку. Это было сделано для кэширования этих экземпляров строк. Типичная программа содержит много строковых ссылок, и кэширование этих экземпляров может уменьшить объем используемой памяти и повысить производительность программы.

При использовании оператора == для сравнения строк вы не сравниваете содержимое строки, а фактически сравниваете адрес памяти. Если они оба равны, он вернет true и false в противном случае. Принимая во внимание, что равно в строке сравнивает содержимое строки.

Таким образом, вопрос в том, все ли строки кэшированы в системе. Почему == возвращает false, а equals возвращает true? Ну, это возможно. Если вы создаете новую строку, такую ​​как String str = new String("Testing"), вы в конечном итоге создаете новую строку в кеше, даже если кеш уже содержит строку с таким же содержимым. Короче говоря, "MyString" == new String("MyString") всегда будет возвращать false.

Java также говорит о функции intern (), которая может использоваться в строке, чтобы сделать ее частью кэша, поэтому "MyString" == new String("MyString").intern() вернет true.

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

172
Faisal Feroz
String a = new String("foo");
String b = new String("foo");
System.out.println(a == b); // prints false
System.out.println(a.equals(b)); // prints true

Убедитесь, что вы понимаете, почему. Это потому, что сравнение == сравнивает только ссылки; метод equals() выполняет посимвольное сравнение содержимого.

Когда вы вызываете new для a и b, каждый получает новую ссылку, которая указывает на "foo" в таблице строк. Ссылки разные, но содержание одинаковое.

142
duffymo

Да, это плохо ...

== означает, что ваши две строковые ссылки являются абсолютно одинаковыми объектами. Возможно, вы слышали, что это так, потому что Java хранит своего рода литеральную таблицу (что она и делает), но это не всегда так. Некоторые строки загружаются по-разному, создаются из других строк и т.д., Поэтому вы никогда не должны предполагать, что две одинаковые строки хранятся в одном месте.

Равный делает реальное сравнение для вас.

125
Uri

Да, == плохо подходит для сравнения строк (любые объекты на самом деле, если вы не знаете, что они канонические). == просто сравнивает ссылки на объекты. .equals() проверяет на равенство. Для строк часто они будут одинаковыми, но, как вы обнаружили, это не гарантируется всегда.

121
cletus

У Java есть пул String, в котором Java управляет выделением памяти для объектов String. Смотрите Строковые пулы в Java

Когда вы проверяете (сравниваете) два объекта с помощью оператора ==, он сравнивает равенство адресов в пуле строк. Если два объекта String имеют одинаковые адресные ссылки, он возвращает true, в противном случае false. Но если вы хотите сравнить содержимое двух объектов String, вы должны переопределить метод equals.

equals на самом деле является методом класса Object, но он переопределяется в класс String и дается новое определение, которое сравнивает содержимое объекта.

Example:
    stringObjectOne.equals(stringObjectTwo);

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

Посмотрим:

String one   = "HELLO"; 
String two   = "HELLO"; 
String three = new String("HELLO"); 
String four  = "hello"; 

one == two;   // TRUE
one == three; // FALSE
one == four;  // FALSE

one.equals(two);            // TRUE
one.equals(three);          // TRUE
one.equals(four);           // FALSE
one.equalsIgnoreCase(four); // TRUE
112
Saurabh Agarwal

== сравнивает ссылки на объекты в Java, и это не исключение для объектов String.

Для сравнения фактического содержимого объектов (включая String) необходимо использовать метод equals.

Если сравнение двух объектов String с использованием == оказывается true, то это потому, что объекты String были интернированы, а виртуальная машина Java имеет несколько ссылок, указывающих на один и тот же экземпляр String. Не следует ожидать, что при сравнении одного объекта String, содержащего то же содержимое, что и другой объект String, с использованием == для оценки как true.

99
coobird

Я согласен с ответом от zacherates.

Но то, что вы можете сделать, это вызвать intern() для ваших не-литеральных строк.

Из примера zacherates:

// ... but they are not the same object
new String("test") == "test" ==> false 

Если вы интернируете не буквальное равенство строк: true

new String("test").intern() == "test" ==> true 
98
pgras

.equals() сравнивает данные в классе (при условии, что функция реализована). == сравнивает местоположение указателя (расположение объекта в памяти).

== возвращает значение true, если оба объекта (НЕ ОБРАЩАЯСЯ О ПРИМИТИВАХ) указывают на тот же экземпляр объекта. .equals() возвращает true, если два объекта содержат одинаковые данные equals() Versus == в Java

Это может помочь вам.

97
Matt Razza

== выполняет проверку равенства ссылка, ссылаются ли два объекта (в данном случае на строки) на один и тот же объект в памяти.

Метод equals() проверяет, совпадают ли --- content или states двух объектов.

Очевидно, что == быстрее, но во многих случаях будет (может) давать ложные результаты, если вы просто захотите узнать, содержат ли 2 Strings один и тот же текст.

Определенно рекомендуется использовать метод equals().

Не беспокойтесь о производительности. Некоторые вещи, которые следует поощрять с помощью String.equals()

  1. Реализация String.equals() сначала проверяет равенство ссылок (используя ==), и если 2 строки одинаковы по ссылке, дальнейшие вычисления не выполняются!
  2. Если 2 строковые ссылки не совпадают, String.equals() затем проверит длину строк. Это также быстрая операция, потому что класс String хранит длину строки, не нужно подсчитывать символы или кодовые точки. Если длины различаются, дальнейшая проверка не выполняется, мы знаем, что они не могут быть равны.
  3. Только если мы продвинемся так далеко, будет фактически сопоставлено содержимое 2 строк, и это будет кратким сравнением: не все символы будут сравниваться, если мы обнаружим несовпадающий символ (в той же позиции в 2 строках ), дальнейшие символы проверяться не будут.

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

93
icza

Если вы похожи на меня, когда я впервые начал использовать Java, я хотел использовать оператор "==", чтобы проверить, равны ли два экземпляра String, но, что бы там ни было, это неправильный способ сделать это в Java.

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

Вариант 1: Java Сравнение строк с помощью метода equals Большую часть времени (возможно, в 95% случаев) я сравниваю строки с метод equals класса Java String, например так:

if (string1.equals(string2))

Этот метод String equals просматривает две строки Java, и если они содержат одинаковую строку символов, они считаются равными.

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

String string1 = "foo";
String string2 = "FOO";

if (string1.equals(string2))
{
    // this line will not print because the
    // Java string equals method returns false:
    System.out.println("The two strings are the same.")
}

Но когда две строки содержат одинаковую строку символов, метод equals вернет true, как в этом примере:

String string1 = "foo";
String string2 = "foo";

// test for equality with the Java string equals method
if (string1.equals(string2))
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Вариант 2. Сравнение строк с помощью метода equalsIgnoreCase

В некоторых тестах сравнения строк вы захотите игнорировать, являются ли строки прописными или строчными. Если вы хотите проверить строки на равенство в этом случае без учета регистра, используйте метод equalsIgnoreCase класса String, например:

String string1 = "foo";
String string2 = "FOO";

 // Java string compare while ignoring case
 if (string1.equalsIgnoreCase(string2))
 {
     // this line WILL print
     System.out.println("Ignoring case, the two strings are the same.")
 }

Вариант 3: Java Сравнение строк с помощью метода CompareTo

Существует также третий, менее распространенный способ сравнения строк Java, и это с помощью метода String класса CompareTo. Если две строки одинаковы, метод compareTo вернет значение 0 (ноль). Вот быстрый пример того, как выглядит этот подход сравнения строк:

String string1 = "foo bar";
String string2 = "foo bar";

// Java string compare example
if (string1.compareTo(string2) == 0)
{
    // this line WILL print
    System.out.println("The two strings are the same.")
}

Хотя я пишу об этой концепции равенства в Java, важно отметить, что язык Java включает метод equals в базовом классе объектов Java. Всякий раз, когда вы создаете свои собственные объекты и хотите предоставить средство, чтобы увидеть, равны ли два экземпляра вашего объекта, вы должны переопределить (и реализовать) этот метод equals в вашем классе (таким же образом Java язык обеспечивает такое поведение равенства/сравнения в методе String equals).

Возможно, вы захотите взглянуть на это ==, .equals (), compareTo () и compare ()

81
Mohamed E. ManSour

Функция:

public float simpleSimilarity(String u, String v) {
    String[] a = u.split(" ");
    String[] b = v.split(" ");

    long correct = 0;
    int minLen = Math.min(a.length, b.length);

    for (int i = 0; i < minLen; i++) {
        String aa = a[i];
        String bb = b[i];
        int minWordLength = Math.min(aa.length(), bb.length());

        for (int j = 0; j < minWordLength; j++) {
            if (aa.charAt(j) == bb.charAt(j)) {
                correct++;
            }
        }
    }

    return (float) (((double) correct) / Math.max(u.length(), v.length()));
}

Тестовое задание:

String a = "This is the first string.";

String b = "this is not 1st string!";

// for exact string comparison, use .equals

boolean exact = a.equals(b);

// For similarity check, there are libraries for this
// Here I'll try a simple example I wrote

float similarity = simple_similarity(a,b);
76
Khaled.K

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

Обратите внимание, что метод .equals() принадлежит классу Object (суперкласс всех классов). Вам необходимо переопределить его в соответствии с требованиями вашего класса, но для String оно уже реализовано, и оно проверяет, имеют ли две строки одинаковое значение или нет.

  • Случай 1

    String s1 = "Stack Overflow";
    String s2 = "Stack Overflow";
    s1 == s2;      //true
    s1.equals(s2); //true
    

    Причина: строковые литералы, созданные без нуля, хранятся в пуле строк в области permgen кучи. Таким образом, s1 и s2 указывают на один и тот же объект в пуле.

  • Случай 2

    String s1 = new String("Stack Overflow");
    String s2 = new String("Stack Overflow");
    s1 == s2;      //false
    s1.equals(s2); //true
    

    Причина: если вы создаете объект String с помощью ключевого слова new, ему выделяется отдельное пространство в куче.

73
Aniket Thakur

== сравнивает эталонное значение объектов, тогда как метод equals(), присутствующий в классе Java.lang.String, сравнивает содержимое объекта String (с другим объектом).

52
samkit shah

Я думаю, что когда вы определяете String, вы определяете объект. Так что вам нужно использовать .equals(). Когда вы используете примитивные типы данных, вы используете ==, но с String (и любым объектом) вы должны использовать .equals().

49
fabricioflores

Если метод equals() присутствует в классе Java.lang.Object, и ожидается, что он проверит эквивалентность состояния объектов! Это означает, что содержимое объектов. Принимая во внимание, что оператор == должен проверять, что фактические экземпляры объекта одинаковы или нет.

пример

Рассмотрим две разные ссылочные переменные, str1 и str2:

str1 = new String("abc");
str2 = new String("abc");

Если вы используете equals()

System.out.println((str1.equals(str2))?"TRUE":"FALSE");

Вы получите вывод как TRUE, если вы используете ==.

System.out.println((str1==str2) ? "TRUE" : "FALSE");

Теперь вы получите FALSE в качестве выходных данных, потому что и str1, и str2 указывают на два разных объекта, даже если оба они имеют одинаковое строковое содержимое. Именно из-за new String() каждый раз создается новый объект.

46
Rakesh KR

Оператор == всегда предназначен для сравнение ссылок на объекты, тогда как класс String . Метод equals () переопределен для сравнение содержимого:

String s1 = new String("abc");
String s2 = new String("abc");
System.out.println(s1 == s2); // It prints false (reference comparison)
System.out.println(s1.equals(s2)); // It prints true (content comparison)
42
sham.y

Вы также можете использовать метод compareTo() для сравнения двух строк. Если результат CompareTo равен 0, то две строки равны, иначе сравниваемые строки не равны.

== сравнивает ссылки и не сравнивает фактические строки. Если вы создали каждую строку с помощью new String(somestring).intern(), то вы можете использовать оператор == для сравнения двух строк, в противном случае можно использовать только методы equals () или compareTo.

38
Balasubramanian Jayaraman

Все объекты гарантированно имеют метод .equals(), так как Object содержит метод .equals(), который возвращает логическое значение. Задача подкласса - переопределить этот метод, если требуется дополнительное определение. Без этого (то есть с использованием ==) только адреса памяти проверяются между двумя объектами на равенство. String переопределяет этот метод .equals() и вместо использования адреса памяти возвращает сравнение строк на уровне символов для равенства.

Ключевым моментом является то, что строки хранятся в одном единственном пуле, поэтому после создания строки она всегда сохраняется в программе по одному и тому же адресу. Строки не меняются, они неизменны. Вот почему плохая идея использовать обычную конкатенацию строк, если у вас есть серьезный объем обработки строки. Вместо этого вы должны использовать предоставленные классы StringBuilder. Помните, что указатели на эту строку могут измениться, и если вам интересно узнать, были ли два указателя одинаковыми, == был бы хорошим вариантом. Сами струны нет.

38
James

В Java, когда оператор "==" используется для сравнения 2 объектов, он проверяет, ссылаются ли объекты на одно и то же место в памяти. Другими словами, он проверяет, являются ли два имени объекта в основном ссылками на одну и ту же ячейку памяти.

Класс Java String фактически переопределяет стандартную реализацию equals () в классе Object, а также метод, переопределяющий только значения строк, а не их расположение в памяти. Это означает, что если вы вызываете метод equals () для сравнения двух строковых объектов, то до тех пор, пока фактическая последовательность символов равна, оба объекта считаются равными.

Оператор == проверяет, являются ли две строки одним и тем же объектом.

Метод .equals() проверяет, имеют ли две строки одинаковое значение.

34
Lijo