Come dividere una stringa in Java


1640

Ho una stringa "004-034556"che voglio dividere in due stringhe:

string1="004";
string2="034556";

Ciò significa che la prima stringa conterrà i caratteri prima '-'e la seconda stringa conterrà i caratteri dopo '-'. Voglio anche verificare se la stringa contiene '-'. In caso contrario, lancerò un'eccezione. Come posso fare questo?

Risposte:


2935

Basta utilizzare il metodo appropriato: String#split().

String string = "004-034556";
String[] parts = string.split("-");
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556

Nota che questo richiede un'espressione regolare , quindi ricorda di scappare da caratteri speciali se necessario.

ci sono 12 caratteri con significati speciali: la barra rovesciata \, il cursore ^, il simbolo del dollaro $, il punto o il punto ., la barra verticale o il simbolo della pipa |, il punto interrogativo ?, l'asterisco o la stella *, il segno più +, la parentesi aperta (, la parentesi chiusa )e la parentesi quadra aperta [, la parentesi graffa aperta {, Questi caratteri speciali sono spesso chiamati "metacaratteri".

Quindi, se si desidera dividere per esempio periodo / puntino .che significa " qualsiasi carattere " in regex, utilizzare uno backslash\ per sfuggire il carattere speciale individuale in questo modo split("\\."), o l'uso classe del personaggio[] per rappresentare carattere letterale (s) in questo modo split("[.]"), o l'uso Pattern#quote()di sfuggire all'intera stringa in questo modo split(Pattern.quote(".")).

String[] parts = string.split(Pattern.quote(".")); // Split on period.

Per verificare in anticipo se la stringa contiene determinati caratteri, basta usare String#contains().

if (string.contains("-")) {
    // Split it.
} else {
    throw new IllegalArgumentException("String " + string + " does not contain -");
}

Nota, questo non richiede un'espressione regolare. Per quello, usa String#matches()invece.

Se desideri conservare il carattere diviso nelle parti risultanti, utilizza una ricerca positiva . Nel caso in cui si desideri che il carattere diviso finisca nella parte sinistra, utilizzare lookbehind positivo prefissando il ?<=gruppo sul modello.

String string = "004-034556";
String[] parts = string.split("(?<=-)");
String part1 = parts[0]; // 004-
String part2 = parts[1]; // 034556

Nel caso in cui si desideri che il carattere diviso finisca nella parte destra, utilizzare un lookahead positivo prefissando il ?=gruppo sul modello.

String string = "004-034556";
String[] parts = string.split("(?=-)");
String part1 = parts[0]; // 004
String part2 = parts[1]; // -034556

Se desideri limitare il numero di parti risultanti, puoi fornire il numero desiderato come secondo argomento del split()metodo.

String string = "004-034556-42";
String[] parts = string.split("-", 2);
String part1 = parts[0]; // 004
String part2 = parts[1]; // 034556-42

27
Perché usi i simboli hash per delimitare i metodi di String?
Crowie,

94
@Crowie: stile javadoc.
BalusC

9
Caso d'angolo: se non lo trova reugalr expressionrestituisce un array di elementi con l'intera stringa.
klimat,

2
Non posso credere che la versione più votata sia così. 1) la parte 2 non è ciò che desidera il poster se la stringa originale contiene due "-" 2) Nessun errore nella gestione come indicato nella domanda. 3) Bassa efficienza. Una ricerca a carattere singolo richiede la costruzione e la corrispondenza di espressioni regolari. Array aggiuntivo creato, ecc.
David

1
@ David: 1) Non è coperto dalla domanda. 2) Non genera eccezioni. 3) OP chiede come dividere, non come sottostringa. 4) Fai una pausa, respira profondamente e distruggi tutta la negatività nella tua testa :)
BalusC

79

Un'alternativa all'elaborazione diretta della stringa sarebbe quella di utilizzare un'espressione regolare con i gruppi di acquisizione. Questo ha il vantaggio che rende semplice implicare vincoli più sofisticati sull'input. Ad esempio, quanto segue divide la stringa in due parti e garantisce che entrambi siano composti solo da cifre:

import java.util.regex.Pattern;
import java.util.regex.Matcher;

class SplitExample
{
    private static Pattern twopart = Pattern.compile("(\\d+)-(\\d+)");

    public static void checkString(String s)
    {
        Matcher m = twopart.matcher(s);
        if (m.matches()) {
            System.out.println(s + " matches; first part is " + m.group(1) +
                               ", second part is " + m.group(2) + ".");
        } else {
            System.out.println(s + " does not match.");
        }
    }

    public static void main(String[] args) {
        checkString("123-4567");
        checkString("foo-bar");
        checkString("123-");
        checkString("-4567");
        checkString("123-4567-890");
    }
}

Poiché il modello è corretto in questa istanza, può essere compilato in anticipo e memorizzato come membro statico (inizializzato al momento del caricamento della classe nell'esempio). L'espressione regolare è:

(\d+)-(\d+)

Le parentesi indicano i gruppi di acquisizione; la stringa che corrisponde a quella parte di regexp è accessibile dal metodo Match.group (), come mostrato. Le corrispondenze \ d e la singola cifra decimale e il + indicano "corrispondono a una o più dell'espressione precedente). Il - non ha alcun significato speciale, quindi corrisponde solo a quel carattere nell'input. Nota che è necessario eseguire il doppio escape delle barre rovesciate quando si scrive questo come una stringa Java. Alcuni altri esempi:

([A-Z]+)-([A-Z]+)          // Each part consists of only capital letters 
([^-]+)-([^-]+)            // Each part consists of characters other than -
([A-Z]{2})-(\d+)           // The first part is exactly two capital letters,
                           // the second consists of digits

Questa è un'ottima soluzione, tuttavia la prima parte dovrebbe essere m.group(1), la seconda parte m.group(2), poiché in m.group(0)realtà restituisce il modello di corrispondenza completo. Penso che ricordo group(0)di essere stata la prima partita invece del modello completo, forse questo è cambiato in un recente aggiornamento della versione Java.
ptstone,

1
Grazie. Guardando docs.oracle.com/javase/7/docs/api/java/util/regex/… , hai ragione - in linea con la maggior parte delle altre librerie regexp, il gruppo 0 è la corrispondenza completa e i gruppi acquisiti iniziano da 1. Come dici tu, sospetto che questo possa essere cambiato da quando ho scritto la risposta originariamente, ma in ogni caso la aggiornerò per riflettere il comportamento attuale.
Rob Hague,

42
String[] result = yourString.split("-");
if (result.length != 2) 
     throw new IllegalArgumentException("String not in correct format");

Questo dividerà la tua stringa in 2 parti. Il primo elemento dell'array sarà la parte che contiene le cose prima del -, e il secondo elemento dell'array conterrà la parte della stringa dopo il- .

Se la lunghezza dell'array non è 2, la stringa non era nel formato: string-string .

Dai un'occhiata al split()metodo nella Stringclasse.

https://docs.oracle.com/javase/8/docs/api/java/lang/String.html#split-java.lang.String-int-


5
Questo accetterà "-555" come input e restituisce [, 555]. I requisiti non sono definiti in modo chiaro, se sarebbe valido accettarlo. Consiglio di scrivere alcuni unit test per definire il comportamento desiderato.
Michael Konietzka,

Probabilmente il più sicuro da cambiare (result.length! = 2) in (result.length <2)
Zio Iroh,

29
String[] out = string.split("-");

dovrebbe fare quello che vuoi. La classe String ha molti metodi per operare con la stringa.


29
// This leaves the regexes issue out of question
// But we must remember that each character in the Delimiter String is treated
// like a single delimiter        

public static String[] SplitUsingTokenizer(String subject, String delimiters) {
   StringTokenizer strTkn = new StringTokenizer(subject, delimiters);
   ArrayList<String> arrLis = new ArrayList<String>(subject.length());

   while(strTkn.hasMoreTokens())
      arrLis.add(strTkn.nextToken());

   return arrLis.toArray(new String[0]);
}

60
JavaDoc afferma chiaramente: " StringTokenizerè una classe legacy che viene mantenuta per motivi di compatibilità sebbene il suo utilizzo sia sconsigliato nel nuovo codice . Si consiglia a chiunque cerchi questa funzionalità di utilizzare il splitmetodo Stringo il java.util.regexpacchetto".
bvdb

23

Con Java 8:

    List<String> stringList = Pattern.compile("-")
            .splitAsStream("004-034556")
            .collect(Collectors.toList());

    stringList.forEach(s -> System.out.println(s));

2
Se si desidera rimuovere gli spazi bianchi aggiungere .map(String::trim)doposplit
Roland

18

I requisiti lasciavano spazio all'interpretazione. Raccomando di scrivere un metodo,

public final static String[] mySplit(final String s)

che incapsulano questa funzione. Ovviamente puoi usare String.split (..) come menzionato nelle altre risposte per l'implementazione.

È necessario scrivere alcuni test unitari per le stringhe di input e i risultati e il comportamento desiderati.

I candidati per i buoni test dovrebbero includere:

 - "0022-3333"
 - "-"
 - "5555-"
 - "-333"
 - "3344-"
 - "--"
 - ""
 - "553535"
 - "333-333-33"
 - "222--222"
 - "222--"
 - "--4555"

Con la definizione dei risultati del test in base, è possibile specificare il comportamento.

Ad esempio, se "-333"dovrebbe tornare [,333]o se si tratta di un errore. Può "333-333-33"essere separato [333,333-33] or [333-333,33]o è un errore? E così via.


4
Consigli utili, ma in realtà non una risposta alla domanda. Se stai supportando un'altra risposta con dettagli, è preferibile un commento.
Chris Mountford,

Usa: split (String regex, int limit) e NOT split (String regex) come riferimento visita geeksforgeeks.org/split-string-java-examples
Ryan Augustine,

16

Puoi provare anche in questo modo

 String concatenated_String="hi^Hello";

 String split_string_array[]=concatenated_String.split("\\^");

16

Supponendo che

  • non hai davvero bisogno di espressioni regolari per la tua divisione
  • ti capita di usare già apache commons lang nella tua app

Il modo più semplice è usare StringUtils # split (java.lang.String, char) . È più conveniente di quello fornito da Java immediatamente se non hai bisogno di espressioni regolari. Come dice il suo manuale, funziona così:

A null input String returns null.

 StringUtils.split(null, *)         = null
 StringUtils.split("", *)           = []
 StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
 StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
 StringUtils.split("a:b:c", '.')    = ["a:b:c"]
 StringUtils.split("a b c", ' ')    = ["a", "b", "c"]

Consiglierei l'uso di commong-lang, poiché di solito contiene molte cose utilizzabili. Tuttavia, se non ne hai bisogno per nient'altro che fare una divisione, implementare te stesso o sfuggire alla regex è un'opzione migliore.


15

Usa il metodo split di org.apache.commons.lang.StringUtils che può dividere le stringhe in base al carattere o alla stringa che desideri dividere.

Firma del metodo:

public static String[] split(String str, char separatorChar);

Nel tuo caso, vuoi dividere una stringa quando c'è un "-".

Puoi semplicemente fare come segue:

String str = "004-034556";

String split[] = StringUtils.split(str,"-");

Produzione:

004
034556

Supponiamo che se -non esiste nella stringa, restituisce la stringa specificata e non otterrai alcuna eccezione.


14

Riassumendo: ci sono almeno cinque modi per dividere una stringa in Java:

  1. String.split ():

    String[] parts ="10,20".split(",");
  2. Pattern.compile (regexp) .splitAsStream (ingresso):

    List<String> strings = Pattern.compile("\\|")
          .splitAsStream("010|020202")
          .collect(Collectors.toList());
  3. StringTokenizer (classe legacy):

    StringTokenizer strings = new StringTokenizer("Welcome to EXPLAINJAVA.COM!", ".");
    while(strings.hasMoreTokens()){
        String substring = strings.nextToken();
        System.out.println(substring);
    }
  4. Google Guava Splitter:

    Iterable<String> result = Splitter.on(",").split("1,2,3,4");
  5. Apache Commons StringUtils:

    String[] strings = StringUtils.split("1,2,3,4", ",");

Quindi puoi scegliere l'opzione migliore per te in base a ciò di cui hai bisogno, ad esempio tipo di ritorno (array, elenco o iterabile).

Ecco una grande panoramica di questi metodi e degli esempi più comuni (come dividere per punto, barra, punto interrogativo, ecc.)


13

Il modo più veloce, che consuma anche la minima risorsa potrebbe essere:

String s = "abc-def";
int p = s.indexOf('-');
if (p >= 0) {
    String left = s.substring(0, p);
    String right = s.substring(p + 1);
} else {
  // s does not contain '-'
}

6
La risorsa più scarsa è spesso il tempo e l'attenzione del programmatore. Questo codice consuma più di quella risorsa rispetto alle alternative.
Chris Mountford,

hai un sacco di risorse integrate che puoi usare, dove le prestazioni sono davvero considerate, questa soluzione è priva di tempi di esecuzione delle prestazioni
J Sanchez,

1
Per eseguire una semplice divisione su un singolo carattere con controllo degli errori, questo non è più complesso della versione regex.
tekHedd,

Bravo! Finalmente una risposta a questa domanda che non usa regex! L'uso di una regex per questo semplice compito è piuttosto un headcratcher. Bello vedere che ci sono ancora programmatori sani di mente su questa terra :-)
Gabriel Magana,

C'è solo un "-", si desidera un'eccezione e il risultato dovrebbe andare a string1 e string2. Fallo string1 = s.substring(0, s.indexOf("-")); string2 = s.substring(s.indexOf("-") + 1);fuori. Riceverai StringIndexOutOfBoundsExceptionautomaticamente se non ci fosse "-".
Kaplan,

13

Dividi stringa con più caratteri usando Regex

public class StringSplitTest {
     public static void main(String args[]) {
        String s = " ;String; String; String; String, String; String;;String;String; String; String; ;String;String;String;String";
        //String[] strs = s.split("[,\\s\\;]");
        String[] strs = s.split("[,\\;]");
        System.out.println("Substrings length:"+strs.length);
        for (int i=0; i < strs.length; i++) {
            System.out.println("Str["+i+"]:"+strs[i]);
        }
     }
  }

Produzione:

Substrings length:17
Str[0]:
Str[1]:String
Str[2]: String
Str[3]: String
Str[4]: String
Str[5]: String
Str[6]: String
Str[7]:
Str[8]:String
Str[9]:String
Str[10]: String
Str[11]: String
Str[12]:
Str[13]:String
Str[14]:String
Str[15]:String
Str[16]:String

Ma non aspettarti lo stesso output in tutte le versioni di JDK. Ho visto un bug che esiste in alcune versioni di JDK in cui la prima stringa null è stata ignorata. Questo errore non è presente nell'ultima versione JDK, ma esiste in alcune versioni tra le versioni successive di JDK 1.7 e le versioni precedenti 1.8.


13

Per casi d'uso semplici String.split()dovrebbe fare il lavoro. Se usi guava, esiste anche una classe Splitter che consente il concatenamento di diverse operazioni di stringa e supporta CharMatcher :

Splitter.on('-')
       .trimResults()
       .omitEmptyStrings()
       .split(string);

10
public class SplitTest {

    public static String[] split(String text, String delimiter) {
        java.util.List<String> parts = new java.util.ArrayList<String>();

        text += delimiter;

        for (int i = text.indexOf(delimiter), j=0; i != -1;) {
            String temp = text.substring(j,i);
            if(temp.trim().length() != 0) {
                parts.add(temp);
            }
            j = i + delimiter.length();
            i = text.indexOf(delimiter,j);
        }

        return parts.toArray(new String[0]);
    }


    public static void main(String[] args) {
        String str = "004-034556";
        String delimiter = "-";
        String result[] = split(str, delimiter);
        for(String s:result)
            System.out.println(s);
    }
}

9

Puoi dividere una stringa per un'interruzione di riga usando la seguente istruzione:

String textStr[] = yourString.split("\\r?\\n");

Puoi dividere una stringa per un trattino / carattere usando la seguente istruzione:

String textStr[] = yourString.split("-");

9
import java.io.*;

public class BreakString {

  public static void main(String args[]) {

    String string = "004-034556-1234-2341";
    String[] parts = string.split("-");

    for(int i=0;i<parts.length;i++) 
      System.out.println(parts[i]);
    }
  }
}

4
se posso condividere un consiglio, in che modo la tua risposta apporta più valore della soluzione già accettata? stackoverflow.com/a/3481842/420096 su tali situazioni puoi votare sulla soluzione esistente, specialmente se questo è un caso banale come quello.
Sombriks,

8

Puoi usare Split ():

import java.io.*;

public class Splitting
{

    public static void main(String args[])
    {
        String Str = new String("004-034556");
        String[] SplittoArray = Str.split("-");
        String string1 = SplittoArray[0];
        String string2 = SplittoArray[1];
    }
}

Altrimenti, puoi usare StringTokenizer:

import java.util.*;
public class Splitting
{
    public static void main(String[] args)
    {
        StringTokenizer Str = new StringTokenizer("004-034556");
        String string1 = Str.nextToken("-");
        String string2 = Str.nextToken("-");
    }
}

8

Ci sono solo due metodi che devi davvero considerare.

Usa String.split per un delimitatore di un carattere o non ti preoccupi delle prestazioni

Se la prestazione non è un problema, o se il delimitatore è un singolo carattere che non è un carattere speciale di espressione regolare (cioè, non uno di .$|()[{^?*+\), è possibile utilizzare String.split.

String[] results = input.split(",");

Il metodo split ha un'ottimizzazione per evitare di usare un'espressione regolare se il delimitatore è un singolo carattere e non nell'elenco precedente. Altrimenti, deve compilare un'espressione regolare, e questo non è l'ideale.

Usa Pattern.split e precompila il pattern se usi un delimitatore complesso e ti preoccupi delle prestazioni.

Se le prestazioni sono un problema e il delimitatore non è uno dei precedenti, è necessario pre-compilare un modello di espressione regolare che è possibile riutilizzare.

// Save this somewhere
Pattern pattern = Pattern.compile("[,;:]");

/// ... later
String[] results = pattern.split(input);

Quest'ultima opzione crea ancora un nuovo Matcheroggetto. Puoi anche memorizzare nella cache questo oggetto e ripristinarlo per ogni input per ottenere le massime prestazioni, ma è un po 'più complicato e non sicuro per i thread.


7

Un modo per eseguire questa operazione è eseguire la stringa in un ciclo for-each e utilizzare il carattere di divisione richiesto.

public class StringSplitTest {

    public static void main(String[] arg){
        String str = "004-034556";
        String split[] = str.split("-");
        System.out.println("The split parts of the String are");
        for(String s:split)
        System.out.println(s);
    }
}

Produzione:

The split parts of the String are:
004
034556

7

Non utilizzare la classe StringTokenizer poiché è una classe legacy che viene conservata per motivi di compatibilità e il suo utilizzo è sconsigliato nel nuovo codice. E possiamo usare il metodo split come suggerito anche da altri.

String[] sampleTokens = "004-034556".split("-");
System.out.println(Arrays.toString(sampleTokens));

E come previsto stamperà:

[004, 034556]

In questa risposta voglio anche sottolineare un cambiamento che ha avuto luogo per il splitmetodo in Java 8 . Il metodo String # split () fa uso di Pattern.splite ora rimuoverà le stringhe vuote all'inizio della matrice dei risultati. Notare questa modifica nella documentazione per Java 8:

Quando c'è una corrispondenza di larghezza positiva all'inizio della sequenza di input, viene inclusa una sottostringa iniziale vuota all'inizio della matrice risultante. Una corrispondenza a larghezza zero all'inizio tuttavia non produce mai una sottostringa iniziale così vuota.

Significa per il seguente esempio:

String[] sampleTokensAgain = "004".split("");
System.out.println(Arrays.toString(sampleTokensAgain));

otterremo tre stringhe: [0, 0, 4]e non quattro come nel caso di Java 7 e precedenti. Controlla anche questa domanda simile .


7

Ecco due modi in cui due lo ottengono.

MODO 1: poiché devi dividere due numeri per un carattere speciale puoi usare regex

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class TrialClass
{
    public static void main(String[] args)
    {
        Pattern p = Pattern.compile("[0-9]+");
        Matcher m = p.matcher("004-034556");

        while(m.find())
        {
            System.out.println(m.group());
        }
    }
}

MODO 2: utilizzando il metodo di suddivisione in stringhe

public class TrialClass
{
    public static void main(String[] args)
    {
        String temp = "004-034556";
        String [] arrString = temp.split("-");
        for(String splitString:arrString)
        {
            System.out.println(splitString);
        }
    }
}

6

Puoi semplicemente usare StringTokenizer per dividere una stringa in due o più parti indipendentemente dal fatto che esista un tipo di delimitatore:

StringTokenizer st = new StringTokenizer("004-034556", "-");
while(st.hasMoreTokens())
{
    System.out.println(st.nextToken());
}

4

Dai un'occhiata al split()metodo nella Stringclasse su javadoc.

https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#split(java.lang.String)

String data = "004-034556-1212-232-232";
int cnt = 1;
for (String item : data.split("-")) {
        System.out.println("string "+cnt+" = "+item);
        cnt++;
}

Qui molti esempi per la stringa divisa, ma ho poco ottimizzato il codice.


Sostituisci -con |e vedi cosa succede :)
R dom


4
String str="004-034556"
String[] sTemp=str.split("-");// '-' is a delimiter

string1=004 // sTemp[0];
string2=034556//sTemp[1];

3

Volevo solo scrivere un algoritmo invece di utilizzare le funzioni integrate di Java:

public static List<String> split(String str, char c){
    List<String> list = new ArrayList<>();
    StringBuilder sb = new StringBuilder();

    for (int i = 0; i < str.length(); i++){
        if(str.charAt(i) != c){
            sb.append(str.charAt(i));
        }
        else{
            if(sb.length() > 0){
                list.add(sb.toString());
                sb = new StringBuilder();
            }
        }
    }

    if(sb.length() >0){
        list.add(sb.toString());
    }
    return list;
}

1

Puoi usare il metodo split:

public class Demo {
    public static void main(String args[]) {
        String str = "004-034556";

        if ((str.contains("-"))) {
            String[] temp = str.split("-");
            for (String part:temp) {
                System.out.println(part);
            }
        }
        else {
            System.out.println(str + " does not contain \"-\".");
        }
    }
}

1

Per dividere una stringa, usa String.split (regex). Esamina i seguenti esempi:

String data = "004-034556";
String[] output = data.split("-");
System.out.println(output[0]);
System.out.println(output[1]);

Produzione

004
034556

Nota:

Questa divisione (regex) accetta una regex come argomento. Ricorda di sfuggire ai caratteri speciali regex, come punto / punto.


0
String s="004-034556";
for(int i=0;i<s.length();i++)
{
    if(s.charAt(i)=='-')
    {
        System.out.println(s.substring(0,i));
        System.out.println(s.substring(i+1));
    }
}

Come accennato da tutti, split () è l'opzione migliore che può essere utilizzata nel tuo caso. Un metodo alternativo può essere l'utilizzo di sottostringa ().


0

Per dividere una stringa, utilizzare String.split(regex):

String phone = "004-034556";
String[] output = phone.split("-");
System.out.println(output[0]);
System.out.println(output[1]);

Produzione:

004
034556
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.