Înțelegerea subșirurilor în Java: un ghid de bază

În acest material, îți vom oferi o perspectivă clară asupra subșirurilor în Java. Nu ne vom limita la explicații teoretice, ci vom oferi și exemple de cod concrete, menite să faciliteze înțelegerea practică. Vei învăța cum să creezi subșiruri și cum să le identifici în cadrul unui șir principal.

Însă, înainte de a ne aprofunda în detalii, este esențial să înțelegem noțiunile fundamentale legate de subșiruri.

Definiția șirurilor și subșirurilor

În universul Java, un șir este, în esență, o secvență de caractere. Fiecare șir în Java este considerat un obiect. Un șir poate include caractere alfanumerice, simboluri și spații. Pe de altă parte, un subșir în Java reprezintă o porțiune sau un segment al unui șir inițial.

Spre exemplu, „Geek” este un subșir al șirului „tipstrick.ro”. Subșirurile sunt utile pentru a extrage anumite părți dintr-un șir mai mare.

Dacă avem numele „Ion Popescu” și dorim să obținem doar prenumele „Ion”, subșirurile sunt soluția perfectă. Mai mult, dacă avem o listă de nume precum „Ion, Maria, Ana” și vrem să verificăm dacă „Ion” se află în listă, subșirurile ne ajută. Acestea sunt doar câteva exemple simple. Utilizarea subșirurilor devine intuitivă odată ce principiile de bază sunt înțelese.

Acum că am clarificat conceptul de subșir în Java, este momentul să explorăm metodele prin care putem crea și manipula subșiruri în Java.

#1. Utilizarea metodei „substring()”

Metoda „substring()” simplifică crearea subșirurilor. Aceasta poate primi unul sau doi parametri: fie doar indexul de început (startIndex), fie indexul de început și cel de sfârșit (startIndex și endIndex). Metoda returnează subșirul dorit.

Putem utiliza metoda în două moduri, în funcție de numărul de parametri. Să le analizăm în detaliu.

subșir (int startIndex)

În varianta „substring(startIndex)”, metoda primește un număr întreg, care reprezintă poziția de la care începe subșirul. Rezultatul este un nou șir, care începe de la indexul specificat și se extinde până la finalul șirului inițial.

Pentru a ilustra acest lucru, iată un exemplu de cod:

public class Substrings{    
    public static void main(String args[]){    
    String str="tipstrick.ro";    
    System.out.println("Șirul original: " + str);  
    System.out.println("Subșirul: " +str.substring(4)); //indexul șirurilor începe de la 0
    }  
   }

REZULTAT:

Șirul original: tipstrick.ro
Subșirul: trick.ro

După cum se poate vedea, șirul original este „tipstrick.ro”, iar subșirul rezultat este „trick.ro”. Metoda creează un subșir de la indexul dat (4), adică de la a cincea poziție, până la sfârșitul șirului.

substring(int startIndex, int endIndex)

Această variantă a metodei subșirurilor primește două numere întregi: indexul de început și indexul de sfârșit. Pentru a utiliza această formă, apelăm metoda ca „substring(startIndex, endIndex)”.

Pentru a înțelege mai bine, să analizăm un alt exemplu de cod:

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareFans";    
    System.out.println("Șirul original: " + str);  
    System.out.println("Subșirul: " +str.substring(4,9));  //Se obține un subșir de la indexul 4 până la indexul 8.

    }  
   }

REZULTAT:

Șirul original: GeekFlareFans
Subșirul: Flare

După cum putem observa, pentru șirul „GeekFlareFans”, am obținut subșirul „Flare”. Am specificat indexul de început ca 4 și indexul de sfârșit ca 9. Subșirul începe de la elementul cu indexul 4 și se termină înainte de elementul cu indexul 9. Este important de reținut că elementul de la indexul de sfârșit nu este inclus în subșirul returnat. Subșirul conține toate elementele până la, dar nu și inclusiv elementul de la indexul de sfârșit.

#2. Utilizarea metodei „split()”

Metoda „split()” este o altă modalitate de a genera subșiruri în Java. Este deosebit de utilă atunci când avem mai multe informații stocate într-un singur șir, separate printr-un caracter comun.

Sintaxa include termenul „regex”, care poate părea intimidant la început. Așadar, să înțelegem ce este un regex înainte de a continua. Regex este o abreviere pentru „Expresii Regulate”. Un regex este o secvență de caractere care definește un anumit model într-un șir sau text. În contextul metodei split, regex este separatorul nostru.

Metoda „split()” acceptă până la două argumente: un șir regex (separatorul) și un număr întreg limită. Atunci când este identificat separatorul (regex), șirul original este divizat în două părți: partea dinaintea separatorului și partea de după separator.

Spre exemplu, dacă dorim să divizăm șirul „abcdef” folosind „bcd” ca separator regex, vom obține subșirurile „a” și „ef”.

Metoda returnează un tablou (matrice) cu șirurile separate. Putem specifica doar separatorul sau și separatorul și limita. Să analizăm ambele posibilități.

split(String regex)

Prima variantă a metodei primește doar șirul regex, sub forma „split(regex)”. Nu există o variabilă limită, astfel încât metoda returnează toate subșirurile separate într-un tablou.

Pentru a înțelege mai bine, să analizăm următorul cod:

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare";
    String[] substrings=str.split("%");
    System.out.println("Șirul original: " + str);
    System.out.println("Primul subșir: " + substrings[0]);
    System.out.println("Al doilea subșir: " + substrings[1]);
     
    }  
}

REZULTAT:

Șirul original: Geek%Flare
Primul subșir: Geek
Al doilea subșir: Flare

După cum se observă în cod, șirul dat are ca separator regex „%”. Separatorul nu trebuie să fie un singur caracter, poate fi orice șir cu un număr variabil de caractere. Metoda „split()” ignoră acest separator și returnează toate șirurile care au fost separate de acesta. Subșirurile sunt stocate într-un tablou.

În cod, șirul dat este „Geek%Flare”. Prin urmare, obținem un tablou cu două elemente: „Geek” și „Flare”. Ulterior, accesăm aceste elemente folosind indicii 0 și 1 și le afișăm în consolă.

De asemenea, este important de menționat că, dacă metoda este apelată fără parametri, aceasta va genera o eroare. Însă, dacă dăm un șir gol („”) ca regex, vom obține fiecare caracter individual ca subșir. Să vedem un exemplu pentru a vizualiza acest aspect.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare";
    String[] substrings=str.split("");
    System.out.println(Arrays.toString(substrings));
     
    }  
}

REZULTAT:

[G, e, e, k, %, F, l, a, r, e]

În acest exemplu, parametrul regex fiind un șir gol, metoda returnează toate caracterele ca subșiruri separate. Acest lucru este vizibil prin afișarea matricei de ieșire a metodei „split()”.

split(String regex, int limit)

Cea de-a doua variantă a metodei ne oferă mai mult control asupra rezultatului și ne permite să ajustăm output-ul metodei „split()”. În acest caz, metoda primește două argumente: separatorul regex și un parametru limită, sub forma „split(regex, limit)”.

„Limita” reprezintă numărul maxim de subșiruri rezultate. În funcție de valoarea limitei, există trei scenarii posibile:

Cazul 1: Dacă limit > 0, tabloul rezultat va conține subșirurile, dar divizarea va fi aplicată de maximum (limită-1) ori. Astfel, tabloul nu va conține mai multe elemente decât limita specificată, iar restul șirului nedivizat va fi stocat ca un singur element. Să ilustrăm acest lucru printr-un exemplu de cod.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%the%best";
    String[] substrings=str.split("%",2);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

REZULTAT:

[Geek, Flare%is%the%best]

După cum se observă, tabloul rezultat conține doar două elemente, conform limitei specificate. De asemenea, divizarea este aplicată o singură dată, adică (limită-1) ori.

Totuși, dacă separatorul regex apare de două ori consecutiv („%%”), vor rezulta subșiruri goale. Să analizăm următorul fragment de cod pentru a înțelege mai bine.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",5);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

REZULTAT:

[Geek, Flare, is, , the%best%%%]

În esență, dacă „%” este urmat de un alt „%” sau de sfârșitul șirului, rezultă un subșir gol.

Cazul 2: Dacă limit < 0, divizarea va fi aplicată de câte ori este posibil, fără a limita dimensiunea tabloului. În acest caz, tabloul poate conține subșiruri goale dacă separatorul regex apare de două ori consecutiv („%%”).

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",-1);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

REZULTAT:

[Geek, Flare, is, , the, best, , , ]

În rezultat, se observă că divizarea este aplicată de câte ori este posibil, și apar și subșiruri goale.

Cazul 3: Dacă limit = 0, divizarea va fi, de asemenea, aplicată de câte ori este posibil, însă toate subșirurile goale de la sfârșitul șirului vor fi eliminate din tablou.

import java.util.Arrays;

public class Substrings{    
    public static void main(String args[]){    
    String str="Geek%Flare%is%%the%best%%%";
    String[] substrings=str.split("%",0);
    System.out.println(Arrays.toString(substrings));
     
    }  
}

REZULTAT:

[Geek, Flare, is, , the, best]

Rezultatul este similar cu cel de la limit=-1, cu excepția faptului că subșirurile goale de la finalul tabloului au fost eliminate.

De asemenea, este important de reținut că, dacă separatorul regex nu este prezent în șir, metoda returnează întregul șir original.

Verificarea prezenței unui subșir într-un șir

Pe lângă crearea de subșiruri din șiruri existente, putem specifica și un subșir și să verificăm dacă acesta există în interiorul unui șir principal. Această operațiune este rapidă și eficientă și este utilă în numeroase situații practice. Să vedem cum putem realiza acest lucru cu ajutorul diferitelor metode.

Utilizarea metodei „contains()”

Metoda „contains()” ne permite să verificăm cu ușurință prezența unui subșir. Această metodă a clasei String primește ca argument un șir, care este subșirul pe care îl căutăm, și returnează o valoare booleană care indică dacă subșirul există sau nu în șirul principal. Metoda poate fi utilizată în instrucțiuni if-else, operatori ternari și în alte contexte pentru a implementa logică complexă.

Să explorăm această metodă în detaliu.

public class Substrings{    
    public static void main(String args[]){    
    String str="tipstrick.ro";    
    System.out.println("Conține subșirul 'Flare'? \n"+ str.contains("Flare"));  
    }  
}

REZULTAT:

Conține subșirul 'Flare'? 
false

Codul verifică dacă șirul „tipstrick.ro” conține cuvântul „Flare”. În acest caz, metoda returnează „false”, indicând absența subșirului.

public class Substrings{    
    public static void main(String args[]){    
    String str="tipstrick.ro";    
    System.out.println("Conține subșirul 'trick'? \n"+ str.contains("trick"));  
    }  
}

REZULTAT:

Conține subșirul 'trick'? 
true

În acest exemplu, metoda „contains()” returnează „true”, confirmând prezența subșirului „trick” în șirul principal. Astfel, putem stabili cu ușurință dacă un subșir există într-un șir.

Determinarea poziției unui subșir

#1. Utilizarea metodei „indexOf()”

Metoda „indexOf()” este utilă pentru a determina prezența unui subșir și pentru a obține indexul acestuia. Metoda primește un șir sau un caracter ca argument și returnează poziția primei apariții a acestuia. Însă, aceasta ne furnizează doar indexul primei apariții și nu poate confirma dacă există și alte apariții. De asemenea, dacă subșirul nu este găsit, metoda returnează -1.

Să explorăm această metodă în continuare.

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareGeekFlare";    
    System.out.println("Indexul lui 'Flare': "+ str.indexOf("Flare"));  
    }  
}

REZULTAT:

Indexul lui 'Flare': 4

În acest exemplu, prima apariție a subșirului „Flare” începe de la indexul 4 din șirul „GeekFlareGeekFlare”. Prin urmare, funcția a returnat indexul corespunzător.

#2. Utilizarea metodei „lastIndexOf()”

Metoda „lastIndexOf()” este similară cu „indexOf()”. Ambele metode primesc ca argument subșirul și returnează indexul poziției acestuia. Ambele returnează -1 în cazul în care subșirul nu este găsit.

Însă, în timp ce „indexOf()” returnează indexul primei apariții a subșirului, „lastIndexOf()” returnează indexul ultimei apariții.

Să vedem cum funcționează în practică:

public class Substrings{    
    public static void main(String args[]){    
    String str="GeekFlareGeekFlare";    
    System.out.println("Ultimul index al lui 'Flare': "+ str.lastIndexOf("Flare"));  
    }  
}

REZULTAT:

Ultimul index al lui 'Flare': 13

Din acest rezultat, se poate observa că metoda „lastIndexOf()” funcționează conform așteptărilor și returnează indexul ultimei apariții a subșirului „Flare” în șirul „GeekFlareGeekFlare”.

Întrebări frecvente

Cum putem utiliza metoda „split()” pentru a crea subșiruri ne-goale?

Dacă există mai multe instanțe consecutive ale separatorului regex (de exemplu, „Bună ziua,%%Salut”, unde regex este „%”), metoda „split()” consideră prima instanță ca separator, iar restul generează subșiruri goale. Pentru a evita acest lucru, putem specifica parametrul limită ca 0. Astfel, metoda va returna doar șiruri ne-goale.

Metoda „indexOf()” returnează indicii tuturor instanțelor unui subșir?

Nu, „indexOf()” nu returnează indicii tuturor instanțelor. Cu „indexOf()”, obținem un număr întreg care reprezintă indexul primei apariții a subșirului. Dacă subșirul nu este găsit, metoda returnează -1.

Ce returnează metoda „substring()” dacă indicii specificați nu există în șir?

Dacă indexul de început sau cel de sfârșit specificat nu există în șir, compilatorul va genera o eroare de tipul „java.lang.StringIndexOutOfBoundsException: ”. Programul pur și simplu nu va rula.

Concluzie

În acest articol, am discutat despre diversele metode și elemente esențiale pentru a lucra cu subșiruri. Am analizat crearea subșirurilor și verificarea prezenței unui subșir într-un șir principal. Aceste informații vă vor oferi o mai bună înțelegere a modului de lucru cu subșiruri. Pentru o înțelegere aprofundată, exersați exemplele prezentate.

De asemenea, vă recomandăm să consultați lista noastră de întrebări pentru interviurile Java.