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

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

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

вопрос задан 4.02.2009
Nathan H
19788 репутация

23 ответов


  • 5042 рейтинг

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

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

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

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

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

    ответ дан Aaron Maenpaa, с репутацией 73676, 4.02.2009
  • 633 рейтинг

    == проверяет ссылки на объекты, .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"));
     

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

     System.out.print(Objects.equals(fooString1, "bar"));
     
    ответ дан Whatsit, с репутацией 5037, 4.02.2009
  • 401 рейтинг

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

    .equals() сравнивает значения String.

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

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

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

    (a == b) ===> true

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

    Однако == не выполняется в следующем случае:

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

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

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

    if (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() всегда лучше.

    ответ дан Ganesh, с репутацией 826, 2.01.2013
  • 204 рейтинг

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

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

    ответ дан Clayton, с репутацией 3487, 4.02.2009
  • 155 рейтинг

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

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

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

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

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

    ответ дан Faisal Feroz, с репутацией 8972, 5.02.2009
  • 134 рейтинг
     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" в таблице строк. Ссылки разные, но контент один и тот же.

    ответ дан duffymo, с репутацией 265638, 4.02.2009
  • 115 рейтинг

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

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

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

    ответ дан Uri, с репутацией 66302, 4.02.2009
  • 110 рейтинг

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

    ответ дан cletus, с репутацией 493765, 4.02.2009
  • 104 рейтинг

    Java имеет пул строк, под которым Java управляет распределением памяти для объектов String. См. String Pools в 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
     
    ответ дан Saurabh Agarwal, с репутацией 278, 2.04.2013
  • 92 рейтинг

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

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

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

    ответ дан Matt Razza, с репутацией 2559, 4.02.2009
  • 91 рейтинг

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

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

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

    ответ дан coobird, с репутацией 130886, 4.02.2009
  • 87 рейтинг

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

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

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

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

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

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

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

    ответ дан icza, с репутацией 150119, 28.03.2013
  • 87 рейтинг

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

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

    Например, из примера zacherates:

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

    Если вы ставите нелитеральное равенство строки, это true

     new String("test").intern() == "test" ==> true 
     
    ответ дан pgras, с репутацией 10621, 5.02.2009
  • 78 рейтинг

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

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

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

     if (string1.equals(string2))
     

    Этот метод String равен методу, который смотрит на две строки 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, и это с помощью метода compareString класса String. Если две строки точно совпадают, метод 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 Object. Всякий раз, когда вы создаете свои собственные объекты, и вы хотите предоставить средства для проверки того, являются ли два экземпляра вашего объекта «равными», вы должны переопределить (и реализовать) этот метод equals в своем классе (точно так же, как язык Java предоставляет это равенство /поведение сравнения в методе String равно).

    Вы можете посмотреть на это ==, .equals (), compareTo () и compare ()

    ответ дан Mohamed E. ManSour, с репутацией 1030, 11.06.2013
  • 73 рейтинг

    Функция:

     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);
     
    ответ дан Khaled.K, с репутацией 4996, 24.03.2013
  • 65 рейтинг

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

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

    • Дело 1

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

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

    • Случай 2

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

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

    ответ дан Aniket Thakur, с репутацией 39595, 25.07.2013
  • 49 рейтинг

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

    ответ дан samkit shah, с репутацией 469, 12.04.2012
  • 47 рейтинг

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

    ответ дан fabricioflores, с репутацией 310, 8.01.2013
  • 41 рейтинг

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

    ответ дан Rakesh KR, с репутацией 4751, 18.12.2013
  • 38 рейтинг

    Оператор == всегда предназначен для сравнения ссылок на объекты , тогда как метод 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)
     
    ответ дан sham.y, с репутацией 591, 30.04.2013
  • 36 рейтинг

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

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

    ответ дан James, с репутацией 55, 3.09.2012
  • 35 рейтинг

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

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

    ответ дан Balasubramanian Jayaraman, с репутацией 285, 29.05.2013
  • 34 рейтинг

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

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

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

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

    ответ дан Lijo, с репутацией 2122, 14.01.2014