Wie vergleiche ich Strings in Java?

724

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

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

Nathan H.
quelle
12
Es ist auch gut zu wissen, dass Sie, wenn Sie die Methode .equals () überschreiben, sicherstellen, dass Sie die Methode .hashcode () überschreiben, da Sie sonst die Äquivalenzbeziehung s / w gleich und den Hashcode verletzen. Weitere Informationen finden Sie in Java Doc.
Nageswaran
Hinterlassen Sie einen Link zu meiner Erklärung, warum ==dies bei Objekten so funktioniert: stackoverflow.com/a/19966154/2284641
Johannes H.
==funktioniert manchmal, da Java über einen String-Pool verfügt, in dem versucht wird, Speicherreferenzen häufig verwendeter Strings wiederzuverwenden. Aber ==vergleicht, dass Objekte gleich sind, nicht die Werte ... so .equals()ist die richtige Verwendung, die Sie verwenden möchten.
James Oravec
Verwenden Sie == niemals, um zu testen, ob Strings identisch sind, es sei denn, Sie möchten subtile Fehler aufspüren und die Feinheiten des internen Java-String-Prozesses untersuchen. "12"=="1"+2ist falsch (wahrscheinlich)
Flug Odyssey

Antworten:

5560

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

.equals() prüft auf Wertgleichheit (ob sie logisch "gleich" sind).

Objects.equals () prüft nullvor dem Aufruf .equals(), ob dies nicht erforderlich ist (verfügbar ab JDK7, auch in Guava verfügbar ).

Wenn Sie also testen möchten, ob zwei Zeichenfolgen denselben Wert haben, möchten Sie wahrscheinlich verwenden 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

Sie möchten fast immer verwenden Objects.equals(). In der seltenen Situation, in der Sie wissen, dass Sie mit internierten Zeichenfolgen zu tun haben , können Sie diese verwenden ==.

Ab JLS 3.10.5. String Literals :

Darüber hinaus bezieht sich ein Zeichenfolgenliteral immer auf dieselbe Klasseninstanz String. Dies liegt daran, dass Zeichenfolgenliterale - oder allgemeiner Zeichenfolgen, die die Werte konstanter Ausdrücke sind ( §15.28 ) - "interniert" werden, um mithilfe der Methode eindeutige Instanzen gemeinsam zu nutzen String.intern.

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

Andere zu berücksichtigende Methoden

String.equalsIgnoreCase () -Wertgleichheit , bei der Groß- und Kleinschreibung ignoriert wird.

String.contentEquals () vergleicht den Inhalt von Stringmit dem Inhalt von any CharSequence(verfügbar seit Java 1.5). Spart Ihnen, dass Sie Ihren StringBuffer usw. vor dem Gleichheitsvergleich in einen String umwandeln müssen, überlässt Ihnen jedoch die Nullprüfung.

Aaron Maenpaa
quelle
3
Wenn == auf Referenzgleichheit prüft, warum ist n == 5 sinnvoll? 5 ist keine Variable
Hrit Roy
2
@HritRoy Da wird ==der Wert einer Variablen überprüft . Wenn Sie ein Objekt haben, hat die Variable, die auf das Objekt verweist, die Objektreferenz als Wert . Daher vergleichen Sie die Referenzen, wenn Sie zwei Variablen mit vergleichen ==. Beim Vergleich eines primitiven Datentyps wie intist dies immer noch der gleiche Fall. Eine Variable vom Typ inthat die Ganzzahl als Wert. So vergleichen Sie die Werte von zwei ints mit ==. Ob das intder Wert einer Variablen oder einer magischen Zahl ist, spielt keine Rolle. Zusätzlich: Eine Referenz ist nichts anderes als eine Zahl, die sich auf den Speicher bezieht.
Akuzminykh
718

==Testet Objektreferenzen, .equals()testet die Zeichenfolgenwerte.

Manchmal sieht es so aus, als würde man ==Werte vergleichen, weil Java einige Dinge hinter den Kulissen tut, um sicherzustellen, dass identische Inline-Zeichenfolgen 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 Vorsicht vor Nullen!

==behandelt nullZeichenfolgen gut, aber das Aufrufen .equals()von 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 dies fooString1möglicherweise null ist, teilen Sie dies dem Leser schriftlich mit

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

Die folgenden sind kürzer, aber es ist weniger offensichtlich, dass nach Null gesucht wird:

System.out.print("bar".equals(fooString1));  // "bar" is never null
System.out.print(Objects.equals(fooString1, "bar"));  // Java 7 required
Whatsit
quelle
86
Manchmal sieht es so aus, als ob "==" Werte vergleicht - vergleichen == Sie immer Werte! (Es ist nur so, dass bestimmte Werte Referenzen sind!)
Aioobe
6
Leider gibt es keine statische Methode für isNullOrEmpty () und keine benutzerdefinierte Überladung von Operatoren, wodurch dieser Teil von Java klobiger wird als in C # oder Python. Und da Java keine Erweiterungsmethoden hat, können Sie kein eigenes Dienstprogramm schreiben, um java.lang.String zu erweitern. Recht? Haben Sie Gedanken darüber, String zu unterklassifizieren, diese statische Dienstprogrammmethode hinzuzufügen und stattdessen immer MyString zu verwenden? Eine statische Methode mit zwei Parametern für nullsichere Vergleiche wäre auch in dieser Unterklasse gut zu haben.
Jon Coombs
7
Groovy macht dies mit dem sicheren Navigationsoperator ( groovy.codehaus.org/… ) etwas einfacher ?.. Das würde sich nullString1?.equals(nullString2);in eine völlig null Aussage umwandeln . Es hilft jedoch nicht, wenn Sie haben validString?.equals(nullString);- das löst immer noch eine Ausnahme aus.
Charles Wood
5
Kurze Methoden zum Vergleichen von nullbaren Zeichenfolgen in Java: stackoverflow.com/questions/11271554/…
Vadzim
5
@ JonCoombs Java unterstützt die Unterklasse und das Erstellen eigener Methoden. Obwohl nur wenige Klassen aus bestimmten Gründen als endgültig markiert sind, ist String eine davon, sodass wir sie nicht erweitern können. Wir können dort eine andere Klasse erstellen und eine Utility-Klasse erstellen, die zwei Zeichenfolgen als Argumente verwendet und dort unsere Logik implementiert. Auch für Null-Check einige andere Bibliotheken wie Spring und Apache er gute Sammlungen von Methoden, kann man das verwenden.
Panther
442

== vergleicht Objektreferenzen.

.equals() vergleicht String-Werte.

Manchmal ==gibt es Illusionen, 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 String-Literals zuerst im String-Pool nach diesem Literal sucht. Wenn eine Übereinstimmung gefunden wird, wird derselbe Verweis auf den neuen String gegeben. Aus diesem Grund erhalten wir:

(a == b) ===> wahr

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

Allerdings ==scheitert im folgenden Fall:

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

In diesem Fall wird für new String("test")die Anweisung eine neue Zeichenfolge auf dem Heap erstellt, und diese Referenz wird angegeben b, sodass beine Referenz auf dem Heap und nicht im Zeichenfolgenpool angegeben wird.

Zeigt jetzt aauf einen String im String-Pool, während bauf einen String im Heap gezeigt wird. Aus diesem Grund erhalten wir:

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

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

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

Während .equals()immer ein Wert von String verglichen wird, gibt es in beiden Fällen wahr:

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

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

Verwenden .equals()ist also immer besser.

Ganesh
quelle
3
.equals () vergleicht die beiden Instanzen, jedoch wird equals implementiert, um sie zu vergleichen. Das könnte sein, dass die Ausgabe von toString verglichen wird oder nicht.
Jacob
3
@ Jacob Object Klassenmethode .equals()vergleicht die Instanzen (Referenzen / Adresse), in denen als String Klassenmethoden .equals()überschrieben werden, um Inhalte (Zeichen) zu vergleichen
Satyadev
1
Es ist gut, auf Unterschiede zwischen String-Pool und Java-Heap hinzuweisen, da diese sicherlich nicht gleich sind. Im String-Pool versucht Java, StringObjekte zu "zwischenspeichern" , um Speicherplatz zu sparen, der als Stringunveränderlich bekannt ist (ich hoffe, ich sage es hier richtig). Überprüfen Sie auch stackoverflow.com/questions/3052442/…
Roland
1
Dies ist die Antwort, nach der ich gesucht habe.
Weezy
Was für eine großartige Antwort!
Alwbtc
223

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

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

Clayton
quelle
5
Generell empfehle ich dringend die Apache Commons Library: commons.apache.org/proper/commons-lang/javadocs/api-2.6/org/… , java.lang.String)
Marcin Erbel
179

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 Zeichenfolgeninstanzen zwischengespeichert werden können. Ein typisches Programm enthält viele Zeichenfolgenreferenzen, und das Zwischenspeichern dieser Instanzen kann den Speicherbedarf verringern und die Leistung des Programms erhöhen.

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 Zeichenfolgeninhalt vergleicht.

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

Java spricht auch über die Funktion intern (), die für eine Zeichenfolge verwendet werden kann, um sie in den Cache aufzunehmen, sodass "MyString" == new String("MyString").intern()true zurückgegeben wird.

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

Faisal Feroz
quelle
147
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. Dies liegt daran, dass der ==Vergleich nur Referenzen vergleicht. Die equals()Methode führt einen zeichenweisen Vergleich des Inhalts durch.

Wenn Sie new for aund aufrufen b, erhält jeder eine neue Referenz, die auf die "foo"in der Zeichenfolgentabelle verweist . Die Referenzen sind unterschiedlich, aber der Inhalt ist der gleiche.

Duffymo
quelle
128

Ja, es ist schlecht ...

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

Gleich macht der echte Vergleich für Sie.

Uri
quelle
124

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

Cletus
quelle
118

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

Wenn Sie zwei Objekte mit dem ==Operator überprüfen (vergleichen), wird die Adressgleichheit mit dem Zeichenfolgenpool verglichen. Wenn die beiden String-Objekte dieselben Adressreferenzen haben true, wird andernfalls zurückgegeben false. Wenn Sie jedoch den Inhalt von zwei String-Objekten vergleichen möchten, müssen Sie die equalsMethode ü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 denken Sie daran, es respektiert den Fall von String. Wenn Sie zwischen Groß- und Kleinschreibung unterscheiden möchten, müssen Sie die Methode equalsIgnoreCase der String-Klasse verwenden.

Wir werden 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
Saurabh Agarwal
quelle
7
Ich sehe, dass dies eine späte Antwort auf eine große Frage ist. Darf ich fragen, was es bietet, was in den vorhandenen Antworten nicht bereits erwähnt ist?
Mysticial
6
@Mysticial hat er hinzugefügt, equalsIgnoreCasewas für die frischeren informativ sein könnte.
AmitG
103

Ich stimme der Antwort von zacherates zu.

Sie können jedoch intern()Ihre nicht wörtlichen Zeichenfolgen aufrufen .

Aus zacherates Beispiel:

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

Wenn Sie intern sind, lautet die nicht wörtliche String-Gleichheit true:

new String("test").intern() == "test" ==> true 
pgras
quelle
8
Dies ist im Allgemeinen keine gute Idee. Internierung ist relativ teuer und kann (paradoxerweise) >> den Speicherbedarf Ihrer JVMs erhöhen und die GC-Kosten erhöhen. In den meisten Fällen überwiegen diese die Leistungsvorteile, die sich aus der Verwendung ==für den Zeichenfolgenvergleich ergeben.
Stephen C
101

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

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

Wenn sich herausstellt , dass ein Vergleich zweier StringObjekte mit verwendet ==wird, liegt dies daran true, dass die StringObjekte interniert wurden und die Java Virtual Machine über mehrere Verweise auf dieselbe Instanz von verfügt String. Man sollte nicht das Vergleichen ein erwartet StringObjekt den gleichen Inhalt wie ein anderes enthält StringObjekt mit ==bewerten , wie true.

Coobird
quelle
99

.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 equals()Versus ==in Java enthalten

Das kann dir helfen.

Matt Razza
quelle
95

==führt eine Referenzgleichheitsprüfung durch, ob sich die beiden Objekte (in diesem Fall Zeichenfolgen) auf dasselbe Objekt im Speicher beziehen.

Die equals()Methode prüft, ob der Inhalt oder der Zustand von 2 Objekten identisch ist.

Offensichtlich ==ist es schneller, führt aber (möglicherweise) in vielen Fällen zu falschen Ergebnissen, wenn Sie nur feststellen möchten, ob 2 Strings denselben Text enthalten.

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

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

  1. Implementierung der String.equals()ersten Überprüfungen auf Referenzgleichheit (unter Verwendung ==), und wenn die 2 Zeichenfolgen durch Referenz gleich sind, wird keine weitere Berechnung durchgeführt!
  2. Wenn die beiden Zeichenfolgenreferenzen nicht identisch sind, String.equals()wird als Nächstes die Länge der Zeichenfolgen überprüft. Dies ist auch eine schnelle Operation, da die StringKlasse die Länge der Zeichenfolge speichert und die Zeichen oder Codepunkte nicht gezählt werden müssen. Wenn sich die Längen unterscheiden, wird keine weitere Überprü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 kurzer Vergleich: Nicht alle Zeichen werden verglichen, wenn wir ein nicht übereinstimmendes Zeichen finden (an derselben Position in den beiden Zeichenfolgen) ) werden keine weiteren Zeichen geprüft.

Wenn alles gesagt und getan ist, selbst wenn wir die Garantie haben, dass die Zeichenfolgen Praktikanten sind, ist die Verwendung der equals()Methode immer noch nicht der Aufwand, den man denken könnte, definitiv der empfohlene Weg. Wenn Sie eine effiziente Referenzprüfung wünschen, verwenden Sie Aufzählungen, bei denen durch die Sprachspezifikation und -implementierung garantiert wird, dass derselbe Aufzählungswert dasselbe Objekt ist (als Referenz).

icza
quelle
2
Obviously == is faster- Eigentlich die Durchführung der .equals(String)ersten Überprüfungen ==vor allem anderen, also würde ich sagen, dass die Geschwindigkeit ungefähr identisch ist.
Razzle Shazl
2
public boolean equals(Object anObject) { if (this == anObject) { return true; } ...
Razzle Shazl
82

Wenn Sie wie ich sind, als ich anfing, Java zu verwenden, wollte ich den Operator "==" verwenden, um zu testen, ob zwei String-Instanzen gleich sind, aber zum Guten oder Schlechten ist dies in Java nicht der richtige Weg.

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

Option 1: Java-String-Vergleich mit der Equals-Methode Die meiste Zeit (möglicherweise 95% der Zeit) vergleiche ich Strings mit der Equals-Methode der Java-String-Klasse wie folgt:

if (string1.equals(string2))

Diese String equals-Methode untersucht die beiden Java-Zeichenfolgen. 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, werden die beiden Zeichenfolgen bei Ausführung des folgenden Tests nicht als gleich angesehen, da die Zeichen nicht exakt 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 jedoch genau dieselbe Zeichenfolge enthalten, gibt die equals-Methode true zurück, wie in diesem 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: Zeichenfolgenvergleich mit der equalsIgnoreCase-Methode

In einigen Zeichenfolgenvergleichstests sollten Sie ignorieren, ob die Zeichenfolgen in Groß- oder Kleinbuchstaben geschrieben sind. Wenn Sie Ihre Zeichenfolgen auf diese Weise ohne Berücksichtigung der Groß- und Kleinschreibung auf Gleichheit testen möchten, verwenden Sie die equalsIgnoreCase-Methode der String-Klasse wie folgt:

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 verbreitete Methode zum Vergleichen von Java-Zeichenfolgen, 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 dafür, 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, ist es wichtig zu beachten, dass die Java-Sprache eine Methode equals in der Basisklasse Java Object 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 die gleiche Weise, wie es die Java-Sprache bietet Dieses Gleichheits- / Vergleichsverhalten in der String-Gleichheitsmethode).

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

Mohamed E. ManSour
quelle
5
für String-Literale wie String string1 = "foo bar"; String string2 = "foo bar"; Sie können den Operator == direkt verwenden, um die Gleichheit der Inhalte zu testen
JAVA
1
Im Google Apps-Skript ist "compareTo" nicht möglich. Ich habe versucht, "gleich" zu installieren. Dies war die einzige Lösung, die funktioniert ...
user3887038
77

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);
Khaled.K
quelle
6
Wie unterscheidet sich das von anderen Antworten? und warum tun Sie es so, wie Sie es vorschlagen
user151019
2
@Mark Die Frage nach dem Unterschied zwischen ==und equalswurde bereits von anderen Lösungen beantwortet. Ich habe nur eine andere Möglichkeit angeboten, Zeichenfolgen auf lose Weise zu vergleichen
Khaled.K
77

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

Beachten Sie, dass die .equals()Methode zur Klasse gehört Object(Superklasse aller Klassen). Sie müssen es gemäß Ihrer Klassenanforderung überschreiben, aber für String ist es bereits implementiert und es wird geprüft, ob zwei Strings 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 String-Literale werden im String-Pool im Permgen-Bereich des Heaps 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 newSchlüsselwort erstellen , wird ihm auf dem Heap ein separater Speicherplatz zugewiesen.

Aniket Thakur
quelle
53

==vergleicht den Referenzwert von Objekten, während die equals()in der java.lang.StringKlasse vorhandene Methode den Inhalt des StringObjekts (mit einem anderen Objekt) vergleicht.

Samkit Shah
quelle
15
nicht wählerisch zu sein, aber die equals()Methode für Stringist tatsächlich in der StringKlasse, nicht in Object. Die Standardeinstellung equals()in Objectwürde nicht vergleichen, dass der Inhalt identisch ist, und gibt tatsächlich nur true zurück, wenn die Referenz identisch ist.
Jacob Schoen
1
@JacobSchoen: Der obige Link funktioniert nicht mehr, da GrepCode nicht verfügbar ist. Hier ist die Alternative für eine gleichwertige Implementierung: [Inline Link] ( zgrepcode.com/java/openjdk/10.0.2/java.base/java/lang/… )
Amandeep Singh
50

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

Fabricioflores
quelle
7
"char []" ist kein primitiver Datentyp! Es ist eine Reihe von "char". Und Arrays sind selbst keine primitiven Datentypen.
Christian
48

Wenn die equals()Methode in der java.lang.ObjectKlasse vorhanden ist und erwartet wird, dass die Äquivalenz des Status von Objekten überprüft wird! Das heißt, der Inhalt der Objekte. Während vom ==Bediener erwartet wird, dass er überprüft, ob die tatsächlichen Objektinstanzen gleich sind oder nicht.

Beispiel

Betrachten Sie zwei verschiedene Referenzvariablen str1und str2:

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

Wenn Sie die verwenden equals()

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

Sie erhalten die Ausgabe so, als TRUEob Sie verwenden ==.

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

Jetzt erhalten Sie die FALSEAusgabe als, da beide str1und str2auf zwei verschiedene Objekte zeigen, obwohl beide denselben Zeichenfolgeninhalt verwenden. Es liegt daran, dass new String()jedes Mal ein neues Objekt erstellt wird.

Rakesh KR
quelle
43

Operator == ist immer für den Objektreferenzvergleich gedacht , während die String-Klasse .equals () für den Inhaltsvergleich überschrieben wird :

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
quelle
40

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

Eine wichtige Anmerkung ist, dass Zeichenfolgen in einem Klumpenpool gespeichert werden. Sobald 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 Zeit für die Verarbeitung von Zeichenfolgen haben. Stattdessen würden Sie die StringBuilderbereitgestellten Klassen verwenden. Denken Sie daran, dass sich die Zeiger auf diese Zeichenfolge ändern können. Wenn Sie interessiert sind, ob zwei Zeiger gleich sind ==, ist dies ein guter Weg. Saiten selbst nicht.

James
quelle
2
"Sobald eine Zeichenfolge erstellt wurde, wird sie für immer in einem Programm unter derselben Adresse gespeichert" - Dies ist absolut falsch. Nur konstante Zeichenfolgenausdrücke zur Kompilierungszeit (möglicherweise mit final StringVariablen) und Zeichenfolgen, die Ihr Programm explizit interniert, werden in einem sogenannten "Lump Pool" gespeichert. Alle anderen StringObjekte unterliegen der Speicherbereinigung, sobald keine Live-Verweise mehr auf sie vorhanden sind, genau wie bei jedem anderen Objekttyp. Auch wenn Unveränderlichkeit erforderlich ist, damit der gesamte Internierungsmechanismus funktioniert, ist dies ansonsten irrelevant.
Ted Hopp
Der String-Vergleich erfolgt entweder mit der Methode equals oder equalsIgnoreCase, mit der der Inhalt des Strings tatsächlich verglichen wird. Aber == Zeichen überprüfen Sie nur die Referenzwerte. Für String-Literale aus dem String-Pool funktioniert dies in diesem Fall einwandfrei. String s1 = neuer String ("a"); String s2 = neuer String ("a"); in diesem Fall ist s1 == s2 falsch, aber s1.equals (s2) ist wahr.
Shailendra Singh
39

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

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

AlvaroAV
quelle
35

In Java, wenn das "==" Operator zum Vergleichen von 2 Objekten verwendet wird, wird überprüft, ob sich die Objekte auf dieselbe Stelle im Speicher beziehen. Mit anderen Worten, es wird geprüft, ob die beiden Objektnamen im Wesentlichen auf denselben Speicherort verweisen.

Die Java-String-Klasse überschreibt tatsächlich die Standardimplementierung equals () in der Object-Klasse - und überschreibt die Methode, sodass nur die Werte der Strings überprüft werden, nicht ihre Speicherorte im Speicher. Dies bedeutet, dass, wenn Sie die Methode equals () aufrufen, um 2 String-Objekte zu vergleichen, beide Objekte als gleich angesehen werden, solange die tatsächliche Zeichenfolge gleich ist.

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

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

Lijo
quelle
1
es sei denn, einer von ihnen ist null, da s.equals (s2) abstürzt, wenn s null ist, was dazu führt, dass der Vergleich fehlschlägt. Dies widerspricht natürlich nicht wirklich der Antwort; Es ist nur eine Einschränkung.
Jon Coombs
1
Nein, es wird nicht abstürzen, es wird eine NullPointerException auslösen, wodurch der Vergleich nicht stattfindet.
Bludzee