Galileo Computing < openbook > Galileo Computing - Professionelle Bücher. Auch für Einsteiger.
Professionelle Bücher. Auch für Einsteiger

 << zurück
Java ist auch eine Insel von Christian Ullenboom
Programmieren für die Java 2-Plattform in der Version 5
Java ist auch eine Insel

Java ist auch eine Insel
5., akt. und erw. Auflage
1454 S., mit CD, 49,90 Euro
Galileo Computing
ISBN 3-89842-747-1
gp Kapitel 4 Der Umgang mit Zeichenketten
  gp 4.1 Strings und deren Anwendung
    gp 4.1.1 String-Literale als String-Objekte für konstante Zeichenketten
    gp 4.1.2 String-Objekte neu anlegen
    gp 4.1.3 String-Länge
    gp 4.1.4 Gut, dass wir verglichen haben
    gp 4.1.5 String-Teile extrahieren
    gp 4.1.6 Suchen und Ersetzen
    gp 4.1.7 Veränderte Strings liefern
    gp 4.1.8 Unterschiedliche Typen in Zeichenketten konvertieren
  gp 4.2 Veränderbare Zeichenketten mit StringBuffer/StringBuilder
    gp 4.2.1 Anlegen von StringBuffer/StringBuilder-Objekten
    gp 4.2.2 Die Länge eines StringBuffer/Builder-Objekts lesen und setzen
    gp 4.2.3 Daten anhängen
    gp 4.2.4 Zeichen(folgen) setzen, erfragen, löschen und umdrehen
  gp 4.3 Vergleiche von Zeichenketten
    gp 4.3.1 equals() in String und StringBuffer/StringBuilder
    gp 4.3.2 equals() und hashCode() bei StringBuffer/StringBuilder
    gp 4.3.3 Sprachabhängiges Vergleichen mit der Collator-Klasse
    gp 4.3.4 Effiziente interne Speicherung für die Sortierung
  gp 4.4 Reguläre Ausdrücke
    gp 4.4.1 Die Klassen Pattern und Matcher
    gp 4.4.2 Mit MatchResult alle Ergebnisse einsammeln
    gp 4.4.3 Das alternative Paket org.apache.regexp
  gp 4.5 Zerlegen von Zeichenketten
    gp 4.5.1 Splitten von Zeichenketten mit split() aus Pattern
    gp 4.5.2 split() in String
    gp 4.5.3 Die Klasse Scanner
    gp 4.5.4 StringTokenizer
    gp 4.5.5 Der BreakIterator als Wort- und Satztrenner
  gp 4.6 Zeichenkodierungen
    gp 4.6.1 Kodierungen für unterschiedliche Codepages
    gp 4.6.2 Andere Klassen zur Konvertierung und das Paket java.nio.charset
    gp 4.6.3 Base64-Kodierung
  gp 4.7 Formatieren von Ausgaben
    gp 4.7.1 Zahlen, Prozente und Währungen mit NumberFormat formatieren
    gp 4.7.2 Dezimalzahlformatierung mit DecimalFormat
    gp 4.7.3 Formatieren mit format() aus String
    gp 4.7.4 Ausgaben formatieren mit MessageFormat


Galileo Computing

4.3 Vergleiche von Zeichenkettedowntop

Zum Vergleichen von Zeichenketten bietet sich naheliegenderweise die bekannte equals()-Methode an. Die ist aber bei StringBuffer/StringBuilder nicht wie erwartet implementiert. Dazu gesellen sich andere Methoden, die zum Beispiel unabhängig von der Groß-/Kleinschreibung vergleichen.


Galileo Computing

4.3.1 equals() in String und StringBuffer/StringBuilder  downtop

Ein Blick in die API-Dokumentation der Klasse String zeigt eine equals()-Methode, mit der Zeichenketten vom Typ String verglichen werden können. Leider vergleicht die Methode nur String/String-Paare, aber keine String/StringBuffer-Paare. Das bedeutet, einen String mit einem StringBuffer bzw. StringBuilder zu vergleichen, führt zwar bei equals() zu keinem Compilerfehler (da equals(Object) alles entgegennimmt), aber auch zu nichts Sinnvollem, da der Vergleich immer false ist. Die Implementierung testet in String, ob das an equals() übergebene Argument instanceof String ist. Eine Möglichkeit des Vergleichs ist daher, mit toString() den StringBuffer in ein String zu überführen und dann die beiden Strings mit equals() zu vergleichen.

Anstatt die Methode equals() der Klasse String für die Vergleiche mit StringBuffer- oder StringBuilder-Objekten zu verwenden, verwenden wir contentEquals(StringBuffer). Die Methode liefert die Rückgabe true, wenn der StringBuffer und der betrachtende String den gleichen Zeicheninhalt haben. Die interne Länge des Puffers spielt keine Rolle. Ist das Argument null, wird eine NullPointerException ausgelöst. Die Methode ist im Parametertyp etwas allgemeiner, denn statt StringBuffer und StringBuilder zu trennen, wird die gemeinsame Schnittstelle erwartet, die beide implementieren:

contentEquals(CharSequence)


Beispiel   Vergleiche einen String mit einem StringBuffer:
String s = "Elektrisch-Zahnbürster";
StringBuffer sb = new StringBuffer( "Elektrisch-Zahnbürster" );
System.out.println( s.equals(sb) );                   // false
System.out.println( s.equals(sb.toString()) );        // true
System.out.println( s.contentEquals(sb.toString()) ); // true

Wollen wir zwei StringBuffer- bzw. StringBuilder-Objekte miteinander vergleichen, werden wir noch mehr enttäuscht. Die Klassen definieren überhaupt keine eigene equals()-Methode. Es gibt zwar eine, doch die wird von der Klasse Object geerbt, und das heißt, nur Objektreferenzen werden verglichen. Wenn also zwei verschiedene StringBuffer/StringBuilder-Objekte mit gleichem Inhalt mit equals() verglichen werden, kommt trotzdem immer false heraus.


Beispiel   Um den inhaltlichen Vergleich von zwei StringBuffer-Objekten zu realisieren, müssen wir diese erst mit toString() in Strings umwandeln.
StringBuffer sb1 = new StringBuffer( "Saftpresse" );
StringBuffer sb2 = new StringBuffer( "Saftpresse" );
boolean b1 = sb1.equals( sb2 );                       // false
boolean b2 = sb1.toString().equals( sb2.toString() ); // true
Natürlich würde es reichen, nur einen StringBuffer mit toString() zu konvertieren und dann mit contentEquals() zu arbeiten.


Galileo Computing

4.3.2 equals() und hashCode() bei StringBuffer/StringBuilder  downtop

Die obige Betrachtung zeigt, dass eine Methode equals(), welche den Inhalt von StringBuffer/StringBuilder-Objekten vergleicht, nicht schlecht wäre. Dennoch besteht das Problem, wann StringBuffer/StringBuilder -Objekte als gleich angesehen werden sollen. Das ist interessant, denn StringBuffer/StringBuilder -Objekte sind nicht nur durch ihren Inhalt bestimmt, sondern auch durch die Größe ihres internen Puffers, ihre Kapazität. Sollte equals() den Rückgabewert true haben, wenn die Inhalte gleich sind, oder nur wenn Inhalt und Puffergröße gleich sind? Da jeder Entwickler andere Ansichten über die Gleichheit besitzt, bleibt es bei dem standardmäßigen Test auf identische Objektreferenzen.

Eine ähnliche Argumentation gilt bei der hashCode()-Methode, die für alle inhaltsgleichen Objekte denselben, im Idealfall eindeutigen Zahlenwert liefert. Die Klasse String besitzt eine hashCode()-Methode, doch StringBuffer/StringBuilder erbt die Implementierung aus der Klasse Object unverändert. Mit anderen Worten: Die Klassen selbst bieten keine Implementierung an.


Galileo Computing

4.3.3 Sprachabhängiges Vergleichen mit der Collator-Klasse  downtop

Mit der java.text.Collator-Klasse ist es möglich, Zeichenketten nach jeweils landesüblichen Kriterien zu vergleichen. So werden die Sprachbesonderheiten jedes Landes beachtet.


Beispiel   Für die deutsche Sprache gilt, dass »ä« zwischen »a« und »b« äquivalent zu »ae« einsortiert wird und nicht so, wie Unicode das Zeichen einordnet: hinter dem »z«. Ähnliches gilt für das »ß«. Auch das Spanische hat seine Besonderheiten im Alphabet. Hier gelten das »ch« und das »ll« als einzelner Buchstabe, die passend einsortiert werden müssen.

Ein Collator-Objekt wird vor seiner Benutzung mit getInstance() erzeugt. Dieser Funktion kann auch ein Argument übergeben werden, mit dem der jeweils gewünschte Ländercode ausgewählt werden kann: getInstance(Locale.GERMAN) ermöglicht richtiges Vergleichen für deutsche Zeichenketten. Die Länderbezeichnungen sind Konstanten aus der Locale-Klasse.


abstract class java.text.  Collator
  implements Comparator<Object>, Cloneable

gp  static Collator getInstance() Liefert einen Collator für die aktuelle Landessprache.
gp  static Collator getInstance( Locale desiredLocale ) Liefert einen Collator für die gewünschte Sprache.
gp  abstract int compare( String source, String target ) Vergleicht die beiden Zeichenketten auf ihre Ordnung. Der Rückgabewert ist entweder <0, 0 oder >0.
gp  int compare( Object o1, Object o2 ) Vergleicht die beiden Argumente auf ihre Ordnung. Ruft compare((String)o1, (String)o2) auf.

Listing 4.3   CollatorDemo.java

import java.util.*;
import java.text.*;
class CollatorDemo
{
  public static void comp( Collator colString aString b )
  {
    if ( col.compare( ab ) < 0 )
      System.out.println( a+" < "+b );
    if ( col.compare( ab ) == 0 )
      System.out.println( a+" = "+b );
    if ( col.compare( ab ) > 0 )
      System.out.println( a+" > "+b );
  }
  public static void main( String[] args )
  {
    Collator col = Collator.getInstance( Locale.GERMAN );
    System.out.println( "Strength = PRIMARY" );
    col.setStrength( Collator.PRIMARY );
    comp( col"abc""ABC" );
    comp( col"Quäken""Quaken" );
    comp( col"boß""boss" );
    comp( col"boß""boxen" );
    System.out.println( "\nStrength =  SECONDARY" );
    col.setStrength( Collator.SECONDARY );
    comp( col"abc""ABC" );
    comp( col"Quäken""Quaken" );
    comp( col"boß""boss" );
    comp( col"boß""boxen" );
    System.out.println( "\nStrength =  TERTIARY" );
    col.setStrength( Collator.TERTIARY );
    comp( col"abc""ABC" );
    comp( col"Quäken""Quaken" );
    comp( col"boß""boss" );
    comp( col"boß""boxen" );
  }
}

Die Ausgabe ist folgende:

Strength = PRIMARY
abc = ABC
Quäken = Quaken
boß = boss
boß < boxen
Strength =  SECONDARY
abc = ABC
Quäken > Quaken
boß = boss
boß < boxen
Strength =  TERTIARY
abc < ABC
Quäken > Quaken
boß > boss
boß < boxen

Die Collator-Klasse besitzt viele sinnvolle Methoden, die über die Vergleichsfunktionalität der String- und StringBuffer/StringBuilder -Klasse hinausgehen. So ist es über die Funktion setStrength() möglich, die Toleranz bei Vergleichen einzustellen. Beispielsweise erkennt der tolerante Vergleich »abc« und »ABC« als gleich.


Galileo Computing

4.3.4 Effiziente interne Speicherung für die Sortierung  toptop

Obwohl sich mit der Collator-Klasse sprachspezifische Vergleiche korrekt umsetzen lassen, ist die Geschwindigkeit gegenüber einem normalen String-Vergleich geringer. Daher bietet die Collator-Klasse die Objektmethode getCollationKey() an, die ein CollationKey-Objekt liefert, das schnellere Vergleiche zulässt.

Collator col = Collator.getInstance( Locale.GERMAN );
CollationKey key1 = col.getCollationKey( "ätzend" );
CollationKey key2 = col.getCollationKey( "Bremsspur" );

Durch CollationKeys lässt sich die Performance bei Vergleichen zusätzlich verbessern, da der landesspezifische String in einen dazu passenden, normalen Java-String umgewandelt wird, der dann schneller gemäß der internen Unicode-Zeichenkodierung verglichen werden kann. Dies bietet sich zum Beispiel beim Sortieren einer Tabelle an, wo mehrere Vergleiche mit dem gleichen String durchgeführt werden müssen. Der Vergleich wird mit compareTo(CollationKey) durchgeführt.


Beispiel   Der Vergleich von key1 und key2 lässt sich durch folgende Zeile ausdrücken.
int comp = key2.compareTo( key1 );
Das Ergebnis ist wie bei der compare()-Methode bei Collator-Objekten entweder <0, 0 oder >0.


final class java.text.  CollationKey
  implements Comparable<CollationKey>

gp  int compareTo( CollationKey target ) Vergleicht zwei CollationKey-Objekte miteinander.
gp  int compareTo( Object o ) Vergleicht den aktuellen CollationKey mit dem angegebenen Objekt. Ruft lediglich compareTo((CollationKey)o) auf.
gp  byte[] toByteArray() Konvertiert den CollationKey in eine Folge von Bytes.
gp  boolean equals( Object target ) Testet die beiden CollationKey-Objekte auf Gleichheit.
gp  String getSourceString() Liefert den String zum CollationKey.
gp  int hashCode() Berechnet den Hashcode für den CollationKey.

abstract class java.text.  Collator
  implements Comparator<Object>, Cloneable

gp  abstract CollationKey getCollationKey( String source ) Liefert einen CollationKey für den konkreten String.
 << zurück




Copyright © Galileo Press GmbH 2005
Für Ihren privaten Gebrauch dürfen Sie die Online-Version natürlich ausdrucken. Ansonsten unterliegt das <openbook> denselben Bestimmungen, wie die gebundene Ausgabe: Das Werk einschließlich aller seiner Teile ist urheberrechtlich geschützt. Alle Rechte vorbehalten einschließlich der Vervielfältigung, Übersetzung, Mikroverfilmung sowie Einspeicherung und Verarbeitung in elektronischen Systemen.


[Galileo Computing]

Galileo Press GmbH, Rheinwerkallee 4, 53227 Bonn, Tel.: 0228.42150.0, Fax 0228.42150.77, info@galileo-press.de