it-swarm.com.de

Wie vergleiche ich Strings in Java?

Ich habe in meinem Programm den Operator == verwendet, um alle meine Zeichenfolgen zu vergleichen. Ich bin jedoch auf einen Fehler gestoßen, habe stattdessen einen in .equals() geändert und den Fehler behoben.

Ist == schlecht? Wann sollte es und sollte es nicht verwendet werden? Was ist der Unterschied?

726
Nathan H

== testet auf Referenzgleichheit (ob es sich um dasselbe Objekt handelt).

.equals() testet auf Wertgleichheit (ob sie logisch "gleich" sind).

Objects.equals () sucht vor dem Aufruf von .equals() nach null, damit Sie dies nicht tun müssen (verfügbar ab JDK7, auch verfügbar in Guava ).

String.contentEquals () vergleicht den Inhalt von String mit dem Inhalt von CharSequence (verfügbar seit Java 1.5).

Wenn Sie also testen möchten, ob zwei Zeichenfolgen denselben Wert haben, sollten Sie wahrscheinlich Objects.equals() verwenden.

// 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

Sie möchten fast immer Objects.equals() verwenden. In der seltenen Situation, in der Sie wissen , dass Sie es mit - zu tun haben interniert Strings, Sie können == verwenden.

From JLS 3.10.5. String Literals :

Außerdem bezieht sich ein String-Literal immer auf die gleiche Instanz der Klasse String. Dies liegt daran, dass Zeichenfolgenliterale - oder generell Zeichenfolgen, die die Werte von konstanten Ausdrücken sind ( §15.28 ) - mit der Methode String.intern "interniert" werden, um eindeutige Instanzen gemeinsam zu nutzen. .

Ähnliche Beispiele finden Sie auch in JLS 3.10.5-1 .

5376
Aaron Maenpaa

== testet Objektreferenzen, .equals() testet die Zeichenkettenwerte.

Manchmal sieht es so aus, als ob == Werte vergleicht, weil Java einige Dinge hinter den Kulissen ausführt, um sicherzustellen, dass identische Inline-Strings tatsächlich dasselbe Objekt sind.

Zum Beispiel:

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";

Aber hüte dich vor Nullen!

== verarbeitet null Zeichenfolgen in Ordnung, aber der Aufruf von .equals() aus einer Nullzeichenfolge führt zu einer Ausnahme:

String nullString1 = null;
String nullString2 = null;

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

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

Wenn Sie also wissen, dass fooString1 möglicherweise null ist, teilen Sie dies dem Leser schriftlich mit

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

Das Folgende ist kürzer, aber es ist weniger offensichtlich, dass nach null gesucht wird (von Java 7):

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

== vergleicht Objektreferenzen.

.equals() vergleicht String-Werte.

Manchmal täuscht == vor, String-Werte zu vergleichen, wie in folgenden Fällen:

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

Dies liegt daran, dass die JVM beim Erstellen eines beliebigen String-Literal zuerst im String-Pool nach diesem Literal sucht. Findet sie eine Übereinstimmung, wird der neue String mit demselben Verweis versehen. Dadurch erhalten wir:

(a == b=> true) ==

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

== schlägt jedoch in folgendem Fall fehl:

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

In diesem Fall wird für new String("test") die Anweisung new String auf dem Heap erstellt, und dieser Verweis wird auf b gegeben, sodass b auf dem Heap einen Verweis erhält, nicht in String-Pool.

Jetzt zeigt a auf einen String im String-Pool, während b auf einen String im Heap zeigt. Dadurch bekommen wir:

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

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

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

Während .equals() immer einen Wert von String vergleicht, gibt es in beiden Fällen 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

Daher ist es immer besser, .equals() zu verwenden.

427
Ganesh

Der Operator == prüft, ob die beiden Zeichenfolgen genau dasselbe Objekt sind.

Die Methode .equals() überprüft, ob die beiden Zeichenfolgen denselben Wert haben.

218
Clayton

Zeichenfolgen in Java sind unveränderlich. Das heißt, wenn Sie versuchen, die Zeichenfolge zu ändern, erhalten Sie eine neue Instanz. Sie können die ursprüngliche Zeichenfolge nicht ändern. Dies wurde durchgeführt, damit diese String-Instanzen zwischengespeichert werden können. Ein typisches Programm enthält viele Zeichenfolgenverweise, und das Zwischenspeichern dieser Instanzen kann den Speicherbedarf verringern und die Leistung des Programms steigern.

Wenn Sie den Operator == für den Zeichenfolgenvergleich verwenden, vergleichen Sie nicht den Inhalt der Zeichenfolge, sondern die Speicheradresse. Wenn beide gleich sind, wird andernfalls true und false zurückgegeben. Während gleich in Zeichenfolge den Inhalt der Zeichenfolge vergleicht.

Die Frage ist also, ob alle Zeichenfolgen im System zwischengespeichert sind. Wie kommt es, dass == false zurückgibt, während gleich true zurückgibt? Nun, das ist möglich. Wenn Sie eine neue Zeichenfolge wie String str = new String("Testing") erstellen, wird am Ende eine neue Zeichenfolge im Cache erstellt, auch wenn der Cache bereits eine Zeichenfolge mit demselben Inhalt enthält. Kurz gesagt, "MyString" == new String("MyString") gibt immer false zurück.

Java spricht auch über die Funktion intern (), die für einen String verwendet werden kann, um diesen Teil des Cache zu machen, sodass "MyString" == new String("MyString").intern() true zurückgibt.

Hinweis: Der Operator == ist viel schneller als der Gleiche, nur weil Sie zwei Speicheradressen vergleichen, aber Sie müssen sicherstellen, dass der Code keine neuen String-Instanzen im Code erstellt. Andernfalls treten Fehler auf.

174
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

Stellen Sie sicher, dass Sie verstehen, warum. Das liegt daran, dass der Vergleich == nur Referenzen vergleicht. Die Methode equals() führt einen zeichenweisen Vergleich der Inhalte durch.

Wenn Sie new für a und b aufrufen, erhält jeder eine neue Referenz, die auf den "foo" in der Zeichenfolgentabelle verweist. Die Referenzen sind unterschiedlich, aber der Inhalt ist der gleiche.

143
duffymo

Ja, es ist schlecht ...

== bedeutet, dass Ihre beiden Zeichenfolgenverweise genau dasselbe Objekt sind. Sie haben vielleicht gehört, dass dies der Fall ist, weil Java eine Art Literal-Tabelle führt (was es tut), aber das ist nicht immer der Fall. Einige Zeichenfolgen werden auf unterschiedliche Weise geladen, bestehen aus anderen Zeichenfolgen usw. Sie dürfen also niemals davon ausgehen, dass zwei identische Zeichenfolgen am selben Speicherort gespeichert sind.

Gleich macht der echte Vergleich für Sie.

126
Uri

Ja, == ist schlecht für den Vergleich von Strings (alle Objekte, es sei denn, Sie wissen, dass sie kanonisch sind). == vergleicht nur Objektreferenzen. .equals() prüft auf Gleichheit. Bei Streichern sind sie oft gleich, aber wie Sie festgestellt haben, ist dies nicht immer garantiert.

122
cletus

Java verfügt über einen String-Pool, in dem Java die Speicherzuordnung für die String-Objekte verwaltet. Siehe String Pools in Java

Wenn Sie zwei Objekte mit dem Operator == prüfen (vergleichen), wird die Gleichheit der Adressen mit dem String-Pool verglichen. Wenn die beiden String-Objekte dieselben Adressreferenzen haben, wird true zurückgegeben, andernfalls false. Wenn Sie jedoch den Inhalt zweier String-Objekte vergleichen möchten, müssen Sie die equals -Methode überschreiben.

equals ist eigentlich die Methode der Object-Klasse, wird jedoch in die String-Klasse überschrieben und es wird eine neue Definition angegeben, die den Inhalt des Objekts vergleicht.

Example:
    stringObjectOne.equals(stringObjectTwo);

Aber beachten Sie, dass es den Fall von String respektiert. Wenn Sie zwischen Groß- und Kleinschreibung unterscheiden möchten, müssen Sie die equalsIgnoreCase-Methode der String-Klasse verwenden.

Mal sehen:

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
114
Saurabh Agarwal

== vergleicht Objektreferenzen in Java, und das ist keine Ausnahme für String Objekte.

Zum Vergleichen des tatsächlichen Inhalts von Objekten (einschließlich String) muss die equals -Methode verwendet werden.

Wenn ein Vergleich von zwei String Objekten unter Verwendung von == zu true führt, liegt dies daran, dass die String Objekte interniert wurden und die Java virtuellen Die Maschine verfügt über mehrere Verweise, die auf dieselbe Instanz von String verweisen. Man sollte nicht erwarten, dass ein String Objekt, das denselben Inhalt wie ein anderes String Objekt enthält, mit == als true ausgewertet wird.

100
coobird

Ich stimme der Antwort von zacherates zu.

Sie können jedoch intern() für Ihre nicht-wörtlichen Zeichenfolgen aufrufen.

Aus zacherates Beispiel:

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

Wenn Sie internieren, lautet die nicht-wörtliche Zeichenfolgengleichheit true

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

.equals() vergleicht die Daten in einer Klasse (vorausgesetzt, die Funktion ist implementiert). == vergleicht Zeigerpositionen (Position des Objekts im Speicher).

== gibt true zurück, wenn beide Objekte (NICHT ÜBER PRIMITIVE SPRECHEN) auf die gleiche Objektinstanz verweisen. .equals() gibt true zurück, wenn die beiden Objekte dieselben Daten enthalten equals() Versus == in Java

Das könnte dir helfen.

98
Matt Razza

== führt eine Referenz Gleichheitsprüfung durch, ob die 2 Objekte (in diesem Fall Strings) auf dasselbe Objekt im Speicher verweisen.

Die Methode equals() prüft, ob die Inhalte oder die Zustände von 2 Objekten identisch sind.

Offensichtlich ist == schneller, kann jedoch in vielen Fällen zu falschen Ergebnissen führen, wenn Sie nur feststellen möchten, ob 2 String denselben Text enthalten.

Auf jeden Fall wird die Verwendung der Methode equals() empfohlen.

Mach dir keine Sorgen über die Leistung. Einige Dinge, die Sie zur Verwendung von String.equals() ermutigen sollten:

  1. Die Implementierung von String.equals() überprüft zunächst die Referenzgleichheit (unter Verwendung von ==), und wenn die beiden Zeichenfolgen dieselbe Referenz sind, wird keine weitere Berechnung durchgeführt!
  2. Wenn die beiden Zeichenfolgenreferenzen nicht identisch sind, überprüft String.equals() als Nächstes die Länge der Zeichenfolgen. Dies ist auch eine schnelle Operation, da die Klasse String die Länge der Zeichenfolge speichert, ohne dass die Zeichen oder Codepunkte gezählt werden müssen. Wenn sich die Längen unterscheiden, wird keine weitere Prüfung durchgeführt, wir wissen, dass sie nicht gleich sein können.
  3. Nur wenn wir so weit gekommen sind, wird der Inhalt der beiden Zeichenfolgen tatsächlich verglichen, und dies ist ein Kurzvergleich: Es werden nicht alle Zeichen verglichen, wenn wir ein nicht übereinstimmendes Zeichen finden (an derselben Position in den beiden Zeichenfolgen) ) werden keine weiteren Zeichen geprüft.

Letztendlich ist die Verwendung der equals() -Methode, auch wenn wir die Garantie haben, dass die Zeichenfolgen intern sind, noch nicht so aufwändig, wie man denkt, definitiv die empfohlene Methode. Wenn Sie eine effiziente Referenzprüfung wünschen, verwenden Sie Aufzählungen, bei denen durch die Sprachspezifikation und -implementierung sichergestellt ist, dass derselbe Aufzählungswert dasselbe Objekt ist (als Referenz).

94
icza

Wenn Sie so sind wie ich, als ich zum ersten Mal mit Java angefangen habe, wollte ich mit dem Operator "==" testen, ob zwei String-Instanzen gleich sind, aber im positiven oder im negativen Fall ist dies nicht die richtige Methode in Java.

In diesem Lernprogramm werde ich verschiedene Möglichkeiten demonstrieren, um Java Zeichenfolgen richtig zu vergleichen, beginnend mit dem Ansatz, den ich die meiste Zeit verwende. Am Ende dieses Tutorials zum Vergleichen von Java-Strings werde ich auch erläutern, warum der Operator "==" beim Vergleichen von Java-Strings nicht funktioniert.

Option 1: Java String-Vergleich mit der Methode equals Die meiste Zeit (vielleicht 95% der Zeit) vergleiche ich Strings mit Die Methode equals der Klasse Java String sieht folgendermaßen aus:

if (string1.equals(string2))

Diese String equals-Methode betrachtet die beiden Zeichenfolgen Java. Wenn sie genau dieselbe Zeichenfolge enthalten, werden sie als gleich angesehen.

Wenn Sie sich ein kurzes Beispiel für einen Zeichenfolgenvergleich mit der Methode equals ansehen und den folgenden Test ausführen, werden die beiden Zeichenfolgen nicht als gleich angesehen, da die Zeichen nicht genau gleich sind (der Fall der Zeichen ist unterschiedlich):

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.")
}

Wenn die beiden Zeichenfolgen genau dieselbe Zeichenfolge enthalten, gibt die Methode equals den Wert true zurück, wie im folgenden Beispiel:

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.")
}

Option 2: String-Vergleich mit der equalsIgnoreCase-Methode

In einigen Zeichenfolgenvergleichstests möchten Sie ignorieren, ob die Zeichenfolgen in Groß- oder Kleinbuchstaben geschrieben sind. Verwenden Sie die equalsIgnoreCase-Methode der String-Klasse wie folgt, wenn Sie Ihre Zeichenfolgen auf Gleichheit prüfen möchten, ohne auf Groß- und Kleinschreibung zu achten:

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.")
 }

Option 3: Java String-Vergleich mit der compareTo-Methode

Es gibt auch eine dritte, weniger gebräuchliche Möglichkeit, Java Zeichenfolgen zu vergleichen, und zwar mit der Methode compareTo der String-Klasse. Wenn die beiden Zeichenfolgen genau gleich sind, gibt die compareTo-Methode den Wert 0 (Null) zurück. Hier ist ein kurzes Beispiel, wie dieser String-Vergleichsansatz aussieht:

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.")
}

Während ich über dieses Konzept der Gleichheit in Java schreibe, muss beachtet werden, dass die Sprache Java eine Methode equals in der Objektklasse base Java enthält. Wenn Sie Ihre eigenen Objekte erstellen und ein Mittel bereitstellen möchten, um festzustellen, ob zwei Instanzen Ihres Objekts "gleich" sind, sollten Sie diese Methode equals in Ihrer Klasse überschreiben (und implementieren) (auf dieselbe Weise das Java liefert dieses Gleichheits-/Vergleichsverhalten in der Methode String equals.

Vielleicht möchten Sie sich das ansehen ==, .equals (), compareTo () und compare ()

82

Funktion:

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

Prüfung:

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);
77
Khaled.K

Der Operator == prüft, ob die beiden Referenzen auf dasselbe Objekt verweisen oder nicht. .equals() Überprüfen Sie den tatsächlichen String-Inhalt (Wert).

Beachten Sie, dass die Methode .equals() zur Klasse Object gehört (Superklasse aller Klassen). Sie müssen es gemäß Ihrer Klassenanforderung überschreiben, aber für String ist es bereits implementiert, und es prüft, ob zwei Zeichenfolgen denselben Wert haben oder nicht.

  • Fall 1

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

    Grund: Ohne Null erstellte Zeichenfolgenliterale werden im Zeichenfolgenpool im permgen-Bereich des Heapspeichers gespeichert. Also zeigen sowohl s1 als auch s2 auf dasselbe Objekt im Pool.

  • Fall 2

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

    Grund: Wenn Sie ein String-Objekt mit dem Schlüsselwort new erstellen, wird ihm auf dem Heap ein separater Speicherplatz zugewiesen.

75
Aniket Thakur

== vergleicht den Referenzwert von Objekten, während die in der Klasse Java.lang.String vorhandene Methode equals() den Inhalt des Objekts String (mit einem anderen Objekt) vergleicht.

53
samkit shah

Ich denke, wenn Sie ein String definieren, definieren Sie ein Objekt. Sie müssen also .equals() verwenden. Wenn Sie primitive Datentypen verwenden, verwenden Sie ==, aber mit String (und jedem Objekt) müssen Sie .equals() verwenden.

50
fabricioflores

Wenn die Methode equals() in der Klasse Java.lang.Object vorhanden ist und erwartet wird, dass sie den Status von Objekten auf Gleichwertigkeit überprüft! Das heißt, der Inhalt der Objekte. Während vom Operator == erwartet wird, dass er prüft, ob die tatsächlichen Objektinstanzen identisch sind oder nicht.

Beispiel

Betrachten Sie zwei verschiedene Referenzvariablen, str1 und str2:

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

Wenn Sie die Funktion equals() verwenden

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

Sie erhalten die Ausgabe als TRUE, wenn Sie == verwenden.

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

Jetzt erhalten Sie FALSE als Ausgabe, da sowohl str1 als auch str2 auf zwei verschiedene Objekte zeigen, obwohl beide den gleichen String-Inhalt haben. Es liegt an new String(), dass jedes Mal ein neues Objekt erstellt wird.

48
Rakesh KR

Operator == ist immer für Objektreferenzvergleich gedacht, wohingegen die String-Klasse . Die Methode equals () wird überschrieben für Inhaltsvergleich:

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)
43
sham.y

Sie können auch die Methode compareTo() verwenden, um zwei Zeichenfolgen zu vergleichen. Wenn das compareTo-Ergebnis 0 ist, sind die beiden Zeichenfolgen gleich, andernfalls sind die verglichenen Zeichenfolgen nicht gleich.

Der == vergleicht die Referenzen und nicht die tatsächlichen Zeichenfolgen. Wenn Sie jede Zeichenfolge mit new String(somestring).intern() erstellt haben, können Sie mit dem Operator == zwei Zeichenfolgen vergleichen. Andernfalls können nur die Methoden equals () oder compareTo verwendet werden.

Für alle Objekte ist eine .equals() -Methode garantiert, da Object eine .equals() -Methode enthält, die einen Booleschen Wert zurückgibt. Es ist die Aufgabe der Unterklasse, diese Methode zu überschreiben, wenn eine weitere definierende Definition erforderlich ist. Ohne sie (d. H. Unter Verwendung von ==) werden nur Speicheradressen zwischen zwei Objekten auf Gleichheit geprüft. String überschreibt diese .equals() -Methode und gibt anstelle der Speicheradresse den Vergleich von Strings auf Zeichenebene für Gleichheit zurück.

Ein wichtiger Punkt ist, dass Zeichenfolgen in einem Pool gespeichert werden. Wenn eine Zeichenfolge erstellt wurde, wird sie für immer in einem Programm unter derselben Adresse gespeichert. Saiten ändern sich nicht, sie sind unveränderlich. Aus diesem Grund ist es eine schlechte Idee, die reguläre Zeichenfolgenverkettung zu verwenden, wenn Sie viel mit der Zeichenfolgenverarbeitung zu tun haben. Stattdessen würden Sie die bereitgestellten Klassen StringBuilder verwenden. Denken Sie daran, dass sich die Zeiger auf diese Zeichenfolge ändern können. Wenn Sie sich dafür interessieren, ob zwei Zeiger gleich sind, ist == ein guter Weg. Saiten selbst nicht.

39
James

Wenn in Java der Operator "==" zum Vergleichen von 2 Objekten verwendet wird, wird geprüft, ob sich die Objekte auf dieselbe Stelle im Speicher beziehen. Mit anderen Worten, es wird geprüft, ob die beiden Objektnamen grundsätzlich auf denselben Speicherort verweisen.

Die String-Klasse Java überschreibt die standardmäßige equals () -Implementierung in der Object-Klasse. Sie überschreibt die Methode, sodass nur die Werte der Strings überprüft werden und nicht deren Speicherorte. Wenn Sie also die Methode equals () aufrufen, um 2 String-Objekte zu vergleichen, werden beide Objekte als gleich betrachtet, solange die tatsächliche Zeichenfolge gleich ist.

Der Operator == prüft, ob die beiden Zeichenfolgen genau dasselbe Objekt sind.

Die Methode .equals() überprüft, ob die beiden Zeichenfolgen den gleichen Wert haben.

35
Lijo