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

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

Is == плохо? Когда его следует и не следует использовать? Какая разница?

23 ответов


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

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

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

строку.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(). В редкая ситуации, когда вы знаю вы имеете дело с интернированы строки, вы можете использовать ==.

С JLS 3.10.5. строка Литералы:

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

аналогичные примеры также можно найти в JLS 3.10.5-1.


== ссылки на объекты тестов,.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 может быть null, скажите читателю, что, написав

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

следующее короче, но менее очевидно, что он проверяет значение null (из Java 7):

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

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

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

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

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

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

(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 указывает на строку в куче. Из-за этого мы получить:

if (a==b) = = = > false.

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

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

пока .equals() всегда сравнивает значение строки, поэтому оно дает 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() всегда лучше.


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

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


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

при использовании оператора == для сравнения строк вы не сравниваете содержимое строки, но на самом деле сравнивают адрес памяти. Если они оба равны, он вернет true и false в противном случае. Тогда как equals in string сравнивает содержимое строки.

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

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

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


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() метод выполняет символьное сравнение содержимого.

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


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

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

Equals делает реальное сравнение для вас.


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


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

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

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

Example:
    stringObjectOne.equals(stringObjectTwo);

но ум его уважает случае строку. Если вы хотите сравнить без учета регистра, вы должны перейти к методу 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

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

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

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


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

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

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


Я согласен с ответом закератов.

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

из примера zacherates:

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

если вы интерн не строковый литерал равенство true

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

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

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

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

наверняка использование метод.

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

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

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


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

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

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

if (string1.equals(string2))

эта строка 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 class 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(), и сравнить()


функция:

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()));
}

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

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

  • случае 1

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

    причина: строковые литералы, созданные без null, хранятся в пуле строк в области 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 ключевое слово отдельное пространство выделено в куче.


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


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


если 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() каждый раз создается новый объект.


оператор == всегда предназначен для сравнение ссылок на объекты, тогда как класс 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)

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

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


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

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


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

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

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

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