Confronto tra Stringhe in Java

Concetti Chiave
  • Java fornisce diversi metodi per confrontare le stringhe, tra cui equals(), compareTo(), e regionMatches().
  • Il metodo equals() confronta due stringhe per l'uguaglianza, mentre compareTo() restituisce un valore che indica se una stringa è minore, uguale o maggiore di un'altra.
  • Il metodo regionMatches() consente di confrontare porzioni specifiche di due stringhe.
  • I metodi startsWith() e endsWith() verificano se una stringa inizia o termina con una determinata sequenza di caratteri.

Confronto tra Stringhe per l'uguaglianza

Per confrontare due stringhe per l'uguaglianza, si può adoperare il metodo equals(). Ha questa forma generale:

boolean equals(Object str)

Qui, str è l'oggetto String che viene confrontato con l'oggetto String che invoca il metodo. Restituisce true se le stringhe contengono gli stessi caratteri nello stesso ordine, e false altrimenti. Il confronto è sensibile alle maiuscole e minuscole.

Per eseguire un confronto che ignora le differenze tra maiuscole e minuscole, chiamiamo equalsIgnoreCase(). Quando si confrontano due stringhe con questo metodo, le lettere A-Z sono considerate come uguali a a-z. Ha questa forma generale:

boolean equalsIgnoreCase(String str)

Qui, str è l'oggetto String che viene confrontato con l'oggetto String che invoca il metodo. Anch'esso restituisce true se le stringhe contengono gli stessi caratteri nello stesso ordine, e false altrimenti.

Ecco un esempio che dimostra equals() e equalsIgnoreCase():

// Dimostra equals() e equalsIgnoreCase().
class demoEquals {

    public static void main(String[] args) {
        String s1 = "Ciao";
        String s2 = "Ciao";
        String s3 = "Arrivederci";
        String s4 = "CIAO";

        System.out.println(s1 + " equals " + s2 + " -> " +
                           s1.equals(s2));

        System.out.println(s1 + " equals " + s3 + " -> " +
                           s1.equals(s3));

        System.out.println(s1 + " equals " + s4 + " -> " +
                           s1.equals(s4));

        System.out.println(s1 + " equalsIgnoreCase " + s4 + " -> " +
                           s1.equalsIgnoreCase(s4));
    }

}

L'output del programma è mostrato qui:

Ciao equals Ciao -> true
Ciao equals Arrivederci -> false
Ciao equals CIAO -> false
Ciao equalsIgnoreCase CIAO -> true

Confronto di porzioni di Stringhe

Il metodo regionMatches() confronta una regione specifica all'interno di una stringa con un'altra regione specifica in un'altra stringa.

Esiste una forma sovraccaricata che consente di ignorare le maiuscole e minuscole in tali confronti.

Ecco le forme generali per questi due metodi:

boolean regionMatches(int indiceInizio,
                      String str2,
                      int str2IndiceInizio,
                      int numCaratteri)
boolean regionMatches(boolean ignoraMaiuscole,
                      int indiceInizio,
                      String str2,
                      int str2IndiceInizio,
                      int numCaratteri)

Per entrambe le versioni, indiceInizio specifica l'indice al quale la regione inizia all'interno dell'oggetto String che invoca il metodo.

La String che viene confrontata è specificata da str2. L'indice al quale il confronto inizierà all'interno di str2 è specificato da str2IndiceInizio. La lunghezza della sotto-stringa che viene confrontata è passata in numCaratteri. Nella seconda versione, se ignoraMaiuscole è true, le maiuscole e minuscole dei caratteri vengono ignorate. Altrimenti, le maiuscole e minuscole sono significative.

Verificare la presenza di un prefisso o suffisso

String definisce due metodi che sono, più o meno, forme specializzate di regionMatches(). Il metodo startsWith() determina se una data String inizia con una stringa specificata. Al contrario, endsWith() determina se la String in questione termina con una stringa specificata.

Hanno le seguenti forme generali:

boolean startsWith(String str)
boolean endsWith(String str)

Qui, str è la String che viene testata. Se la stringa corrisponde, viene restituito true. Altrimenti, viene restituito false. Per esempio,

"Foobar".endsWith("bar")

e

"Foobar".startsWith("Foo")

sono entrambi true.

Una seconda forma di startsWith(), mostrata qui, permette di specificare un punto di partenza:

boolean startsWith(String str, int startIndex)

Qui, startIndex specifica l'indice nella stringa chiamante al quale punto inizierà la ricerca. Per esempio,

"Foobar".startsWith("bar", 3)

restituisce true.

Differenza tra equals e ==

È importante comprendere che il metodo equals() e l'operatore == eseguono due operazioni diverse. Come appena spiegato, il metodo equals() confronta i caratteri all'interno di un oggetto String. L'operatore == confronta due riferimenti di oggetti per vedere se si riferiscono alla stessa istanza.

Il seguente programma mostra come due diversi oggetti String possano contenere gli stessi caratteri, ma i riferimenti a questi oggetti non risulteranno uguali nel confronto:

// equals() vs ==
class EqualsNonUgualeA {

    public static void main(String[] args) {
        String s1 = "Ciao";
        String s2 = new String(s1);

        System.out.println(s1 + " equals " + s2 + " -> " +
                           s1.equals(s2));

        System.out.println(s1 + " == " + s2 + " -> " + (s1 == s2));
    }

}

La variabile s1 si riferisce all'istanza String creata da "Ciao". L'oggetto a cui si riferisce s2 è creato con s1 come inizializzatore. Pertanto, i contenuti dei due oggetti String sono identici, ma sono oggetti distinti. Questo significa che s1 e s2 non si riferiscono agli stessi oggetti e non sono, quindi, ==, come mostrato qui dall'output dell'esempio precedente:

Ciao equals Ciao -> true
Ciao == Ciao -> false

Comparare Stringhe con compareTo

Spesso, non è sufficiente sapere semplicemente se due stringhe sono identiche.

Per le applicazioni di ordinamento, è necessario sapere quale stringa è minore di, uguale a, o maggiore di un'altra.

Una stringa è minore di un'altra se viene prima dell'altra nell'ordine del dizionario. Una stringa è maggiore di un'altra se viene dopo l'altra nell'ordine del dizionario. Questo ordine prende il nome di ordine lessicografico.

Il metodo compareTo() serve a questo scopo. È specificato dall'interfaccia Comparable<T>, che String implementa.

Ha questa forma generale:

int compareTo(String str)

Qui, str è la String che viene confrontata con la String invocante. Il risultato del confronto viene restituito e viene interpretato come mostrato qui:

Valore Significato
Minore di zero La stringa invocante è minore di str.
Maggiore di zero La stringa invocante è maggiore di str.
Zero Le due stringhe sono uguali.
Tabella 1: Risultati dell'operazione di comparazione e loro significato.

Ecco un programma di esempio che ordina un array di stringhe. Il programma usa compareTo() per determinare l'ordine di ordinamento per un bubble sort:

// Un bubble sort per ordinare un array di stringhe.

class OrdinaStringa {

    static String[] arr = {
        "Nel",
        "mezzo",
        "del",
        "cammin",
        "di",
        "nostra",
        "vita",
        "mi",
        "ritrovai",
        "per",
        "una",
        "selva",
        "oscura",
        "che",
        "la",
        "diritta",
        "via",
        "era",
        "smarrita"
    };

    public static void main(String[] args) {
        for(int j = 0; j < arr.length; j++) {
            for(int i = j + 1; i < arr.length; i++) {
                if(arr[i].compareTo(arr[j]) < 0) {
                    String t = arr[j];
                    arr[j] = arr[i];
                    arr[i] = t;
                }
            }
            System.out.println(arr[j]);
        }
    }

}

L'output di questo programma è la lista delle parole:

Nel
cammin
che
del
di
diritta
era
la
mezzo
mi
nostra
oscura
per
ritrovai
selva
smarrita
una
via
vita

Come si può vedere dall'output di questo esempio, compareTo() tiene conto delle lettere maiuscole e minuscole. La parola "Nel" è uscita prima di tutte le altre perché inizia con una lettera maiuscola, il che significa che ha un valore più basso nel set di caratteri ASCII.

Se si vuole ignorare le differenze di maiuscole e minuscole quando si confrontano due stringhe, bisogna usare compareToIgnoreCase(), come mostrato qui:

int compareToIgnoreCase(String str)

Questo metodo restituisce gli stessi risultati di compareTo(), tranne che le differenze di maiuscole e minuscole vengono ignorate. Provando a sostituirlo nel programma precedente, otteniamo il seguente output:

cammin
che
del
di
diritta
era
la
mezzo
mi
Nel
nostra
oscura
per
ritrovai
selva
smarrita
una
via
vita