Stringvergleich

Status
Nicht offen für weitere Antworten.
J

java.coder

Gast
Code:
class Stringvergleich
{
  String s = "vergleich";
  String m = "vergleich";
  
  public Stringvergleich()
  {
    if(s.compareTo(m) == 0)
      System.out.println("s.compareTo(m) == 0");
    if(s.equals(m))
      System.out.println("s.equals(m)");
    if(s == m)
      System.out.println("s == m");
  }
  
  public static void main(String[] argv)
  {
    new Stringvergleich();
  }
}

Die Ausgabe ist 3 mal das was im System.out.println drinsteckt. Heißt das nun, dass die Zeiger des Strings (Objekte?) gleich sind? Das kann aber doch nicht sein, denn der Inhalt dieser Strings sind gleich, oder denke ich da zu kompliziert.

Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?
 

Wildcard

Top Contributor
equals vegleicht den Inhalt, compareTo ob das eine größer als das andere ist und == ob es sich um ein identisches Objekt handelt.
 

hansz

Aktives Mitglied
Das kurze Listing zeigt ein Beispiel zu equals und dem "=="-Operator:

Code:
/* Test.java */

public class Test {
 
  public static void main(String[] args) {
   
    String s1 = "Hallo";
    String s21 = "Hallo";
    String s22 = new String("Hallo");
   
    // Vergleich: s1 mit s21
    if (s1 == s21) {
      System.out.println("Die Strings s1 und s21 sind gleich (==).");
    } else {
      System.out.println("Die Strings s1 und s21 sind nicht gleich (==).");
    }
     
    if (s1.equals(s21)) {
      System.out.println("Die Strings s1 und s21 sind gleich (equals).");
    } else {
      System.out.println("Die Strings s1 und s21 sind nicht gleich (equals).");
    }
   
    // Vergleich: s1 mit s22
    if (s1 == s22) {
      System.out.println("Die Strings s1 und s22 sind gleich (==).");
    } else {
      System.out.println("Die Strings s1 und s22 sind nicht gleich (==).");
    }
     
    if (s1.equals(s22)) {
      System.out.println("Die Strings s1 und s22 sind gleich (equals).");
    } else {
      System.out.println("Die Strings s1 und s22 sind nicht gleich (equals).");
    }
   
  }
}


Ausgabe:
Die Strings s1 und s21 sind gleich (==).
Die Strings s1 und s21 sind gleich (equals).
Die Strings s1 und s22 sind nicht gleich (==).
Die Strings s1 und s22 sind gleich (equals).


"Die Strings s1 und s21 sind gleich (==)." - gleiche String-Objekte.
"Die Strings s1 und s22 sind nicht gleich (==)." - unterschiedliche String-Objekte.


Innerhalb von String.java (im JDK) wird die Methode compareTo wie folgt definiert: :autsch:

/**
* Compares two strings lexicographically.
* The comparison is based on the Unicode value of each character in
* the strings. The character sequence represented by this
* <code>String</code> object is compared lexicographically to the
* character sequence represented by the argument string. The result is
* a negative integer if this <code>String</code> object
* lexicographically precedes the argument string. The result is a
* positive integer if this <code>String</code> object lexicographically
* follows the argument string. The result is zero if the strings
* are equal; <code>compareTo</code> returns <code>0</code> exactly when
* the {@link #equals(Object)} method would return <code>true</code>.

*


* This is the definition of lexicographic ordering. If two strings are
* different, then either they have different characters at some index
* that is a valid index for both strings, or their lengths are different,
* or both.
If they have different characters at one or more index
* positions, let k be the smallest such index; then the string
* whose character at position k has the smaller value, as
* determined by using the & operator, lexicographically precedes the
* other string. In this case, <code>compareTo</code> returns the
* difference of the two character values at position <code>k</code> in
* the two string -- that is, the value:
* <blockquote><pre>
* this.charAt(k)-anotherString.charAt(k)
* </pre></blockquote>
* If there is no index position at which they differ, then the shorter
* string lexicographically precedes the longer string. In this case,
* <code>compareTo</code> returns the difference of the lengths of the
* strings -- that is, the value:
* <blockquote><pre>
* this.length()-anotherString.length()
* </pre></blockquote>

*
* @param anotherString the <code>String</code> to be compared.
* @return the value <code>0</code> if the argument string is equal to
* this string; a value less than <code>0</code> if this string
* is lexicographically less than the string argument; and a
* value greater than <code>0</code> if this string is
* lexicographically greater than the string argument.
*/
public int compareTo(String anotherString) {
int len1 = count;
int len2 = anotherString.count;
int n = Math.min(len1, len2);
char v1[] = value;
char v2[] = anotherString.value;
int i = offset;
int j = anotherString.offset;

if (i == j) {
int k = i;
int lim = n + i;
while (k < lim) {
char c1 = v1[k];
char c2 = v2[k];
if (c1 != c2) {
return c1 - c2;
}
k++;
}
} else {
while (n-- != 0) {
char c1 = v1[i++];
char c2 = v2[j++];
if (c1 != c2) {
return c1 - c2;
}
}
}
return len1 - len2;
}


Gruß,
hansz
 

byte

Top Contributor
java.coder hat gesagt.:
Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?

Du solltest Strings auf Gleichheit immer mit equals vergleichen. In diesem Fall liefert == zwar auch das "richtige" Ergebnis, das liegt aber nur daran, dass Du sie per String-Literal erzeugst. Das heisst, beim zweiten String merkt er, dass dieser schon existiert und setzt ne Referenz drauf. Wenn Du die Strings stattdessen mit new erzeugst, solltest Du an dieser Stelle ein anderes Ergebnis bekommen.

Du brauchst Dir aber prinzipiell nur merken: Inhaltliche Gleichheit immer mit equals, == nur bei Objektgleichheit und compareTo bei größer/kleiner Vergleich.
 
G

Guest

Gast
java.coder hat gesagt.:
Heißt das nun, dass die Zeiger des Strings (Objekte?) gleich sind?
Die zwei Referenzvariablen namens s und m zeigen beide auf das selbe unbenannte String-Objekt, welches den Inhalt "vergleich" hat. Das liegt daran, dass String-Objekte, welche durch gleiche Literalausdrücke erzeugt werden, nach Möglichkeit zusammengefasst werden (d.h. wenn die Zeichenketten übereinstimmen). Das geht sogar über Package-Grenzen hinweg.

java.coder hat gesagt.:
Das kann aber doch nicht sein, denn der Inhalt dieser Strings sind gleich, oder denke ich da zu kompliziert.
Identität und Gleichheit existieren nicht orthogonal zueinander. Es gibt folgende Beziehung zwischen ihnen:

identisch => gleich

s und m zeigen auf das SELBE String-Objekt. Das impliziert, dass equals true zurückliefern MUSS, denn schliesslich vergleichst Du ein String-Objekt mit sich selbst. Anderes Beispiel: Wenn Du Thomas fragst, ob er die gleiche Augenfarbe hat wie Thomas, dann wird er IMMER ja antworten.

a.equals(a) muss immer true zurückliefern, also auch a.equals(b) falls a == b. Bezogen auf Thomas: Wenn Du Thomas' Mutter fragst, ob ihr Sohn die gleiche Augenfarbe hat wie der Sohn ihres Mannes, was wird sie dann antworten? ;)

java.coder hat gesagt.:
Und welche dieser 3 sollte ich generell für Stringvergleiche hernehmen (um auf Gleichheit zu überprüfen)?
Falls Du den Inhalt der String-Objekte miteinander vergleichen möchtest, dann nimm IMMER die equals-Methode. Der Trick, dass gleiche Stringinhalte in gleichen String-Objekten resultieren, funktioniert nur für die zur Kompilierzeit konstanten Stringliterale. Wenn Du dagegen z.B. einen Benutzer zur Laufzeit aufforderst, etwas einzugeben (oder wenn Du aus einer Datei liest oder oder oder...), dann wird daraus IMMER ein neues String-Objekt, unabhängig davon, ob es bereits ein anderes mit dem gleichen Inhalt gibt.

In Deinem Beispiel gibt es übrigens keinen Grund, ein Objekt von Stringvergleich zu erzeugen und dann im Konstruktor die Arbeit durchzuführen. Mach es doch gleich in der main-Methode, das ist konzeptionell sauberer:

Code:
class Stringvergleich
{
  public static void main(String[] argv)
  {
    String s = "vergleich";
    String m = "vergleich";
    if(s.compareTo(m) == 0)
      System.out.println("s.compareTo(m) == 0");
    if(s.equals(m))
      System.out.println("s.equals(m)");
    if(s == m)
      System.out.println("s == m");
  }
}

Fred
 
Status
Nicht offen für weitere Antworten.

Ähnliche Java Themen

Neue Themen


Oben