Java OCPJP7: split di stringhe e regexp

La classe String mette a disposizione un metodo split che permette di separare una stringa in diverse parti utilizzando un separatore passato come parametro e costituito da una stringa rappresentante un’espressione regolare.

String[] split(String regex)

Si tratta di una funzionalità basilare di Java che non nasconde in se nessuna difficoltà intrinseca. In ottica OCPJP7 le cose che possono creare qualche complicazione e trarre in inganno sono 2:

  • L’espressione regolare utilizzata come separatore
  • L’utilizzo dell’overload del metodo che prende in input un secondo parametro

La signature di questa seconda versione del metodo è la seguente:

String[] split(String regex, int limit)

In questo caso, si indica al metodo di splittare la stringa in un numero massimo di parti, unendo tutte le eventuali parti in eccesso nell’ultima.

Vediamo qualche esempio:

Nel primo caso utilizziamo il metodo split per dividere la stringa in base ad un separatore semplice, costituito da un unico carattere, lo spazio:

public class JavaCertification {
	public static void main(String[] args) {
		String s = "We need to split this string.";
		String[] list = s.split(" ");
		for (String ss: list)
			System.out.println(ss);
	}
}

Il risultato dell’esecuzione è il seguente:

We
need
to
split
this
string.

Abbiamo ottenuto, come desiderato, la suddivisione della stringa originale nelle varie stringhe separate tra loro da uno spazio.

Vediamo invece adesso un esempio in cui viene utilizzata un’espressione regolare come separatore per splittare la stringa: l’obbiettivo, in questo caso, è ottenere la lista delle sole stringhe che non contengono cifre numeriche. Per farlo, dobbiamo utilizzare come separatore, una sequenza di spazi o cifre numeriche composta da 1 o più elementi (notare la separazione tra “EF” e “GH”).

Senza entrare nel dettaglio della sintassi delle espressioni regolari, che analizziamo in dettaglio in un altro post, vediamo gusto qualche regola di base che useremo negli esempi seguenti:

\s indica un carattere di spaziatura
\S indica un carattere che NON sia uno spazio
\d indica una cifra numerica
\D indica un carattere che NON sia una cifra numerica
| matcha o il carattere prima dell’operatore o quello dopo (esempio: a|b match “un carattere ‘a’ oppure un carattere ‘b'”)
+ indica 1 o più occorrenze dell’espressione che lo precede
* indica 0 o più occorrenze dell’espressione che lo precede

Attenzione quindi a distinguere le minuscole (\d) dalle maiuscole (\D) nelle sequenze di escape che hanno un significato particolare nelle espressioni regolari ed a ricordare con precisione cosa matchano.

Torniamo ora al nostro esempio:

public class JavaCertification {
	public static void main(String[] args) {
		String s = "ABC 12 D 3 EF GH 45";
		String[] list = s.split("(\\s|\\d)+");
		for (String ss: list)
	                System.out.println(ss);
	}
}

Ed ecco il risultato:

ABC
D
EF
GH

In questo caso, magari per la fretta dovuta all’esame, può essere facile confondersi con espressioni regolari simili che però non tengono in considerazione qualche caso particolare.
Ad esempio, se l’espressione regolare fosse come nel caso seguente, rappresenterebbe il concetto “uno o più spazi, seguiti da 0 o più cifre numeriche, seguite a loro volta da uno o più spazi” e potrebbe sembrare equivalente alla precedente, ma il risultato sarebbe leggermente diverso:

public class JavaCertification {
	public static void main(String[] args) {
		String s = "ABC 12 D 3 EF GH 45";
		String[] list = s.split("\\s+\\d*\\s+");
		for (String ss: list)
			System.out.println(ss);
	}
}

Il risultato in questo in caso è:

ABC
D
EF GH 45

Tra “EF” e “GH” c’è un solo spazio, per cui l’espressione regolare precedente non lo matcha come separatore e quindi l’ultima stringa risulta in “EF GH 45”. Nell’esame OCPJP7, quando le domande comprendono operazioni sulle espressioni regolari, le risposte spesso differiscono di poco tra loro per cui occorre davvero prestare molta attenzione.

Vediamo ora un caso in cui utilizziamo il metodo split passandogli un secondo parametro che identifica il numero massimo di stringhe che vogliamo produrre con l’operazione di split:

public class JavaCertification {
	public static void main(String[] args) {
		String s = "We need to split this string.";
		
		// indichiamo di generare al massimo 3 stringhe
		String[] list = s.split(" ", 3);

		for (String ss: list)
			System.out.println(ss);
	}
}

Il risultato che otteniamo è:

We
need
to split this string.

Vengono in questo modo create le prime due stringhe e poi tutti le parti successive vengono comunque inserite nella terza, nonostante ci siano ancora diverse occorrenze del separatore. Questo perché, tramite il secondo parametro, abbiamo indicato al metodo split di crearci al massimo 3 stringhe.

Leave a Reply

Your email address will not be published. Required fields are marked *