2013-02-15 9 views
13

Poiché il quesito stati trovati il ​​codice seguente:Java String.split passare in regex precompilata per performance ragiona

public class Foo 
{ 
    public static void main(String[] args) 
    { 
     String test = "Cats go meow"; 
     String[] tokens = test.split(" "); 
    } 
} 

è possibile precompilare che regex in funzione split lungo le linee di questo:

public class Foo 
{ 
    Pattern pattern = Pattern.compile(" "); 
    public static void main(String[] args) 
    { 
     String test = "Cats go meow"; 
     String[] tokens = test.split(pattern); 
    } 
} 
+0

split (" ") è più veloce (vedi commento qui sotto) –

+0

@michael_s ho aggiunto un commento, vi preghiamo di contrastare. – Woot4Moo

risposta

17

Sì, è possibile. Inoltre, creare pattern statico in modo che il metodo statico main possa accedervi.

public class Foo 
{ 
    private static Pattern pattern = Pattern.compile(" "); 
    public static void main(String[] args) 
    { 
     String test = "Cats go meow"; 
     String[] tokens = pattern.split(test); 
    } 
} 

Secondo il docs per il metodo split in String, è possibile utilizzare di corde split o Pattern di split, ma String di split compila un Pattern e chiama il suo metodo split, in modo da utilizzare Pattern di precompilare una regex.

+0

Sì 'Pattern # split (string)' è circa il 25% più veloce. Vedi perf benchmark di Oracle (diapositiva 72) https://shipilev.net/talks/joker-Oct2014-string-catechism.pdf – ruhong

3

Uso Pattern.split() invece:

String[] tokens = pattern.split(test); 
+0

hmm in realtà, questo non risolve la pre-compilazione del pattern in quanto è il passo di compilazione che richiede il "più" tempo – Woot4Moo

+0

@ Woot4Moo: Non capisco la tua ultima osservazione. Una volta che hai un'istanza di 'Pattern', la regex è stata compilata, e' pattern.split() 'non richiede ulteriori compilazioni. – NPE

+0

Errore mio. Ho pensato che esistesse un modo per istanziare Pattern da solo. – Woot4Moo

5
public class Foo 
{ 
    private static final Pattern pattern = Pattern.compile(" "); 
    public static void main(String[] args) 
    { 
     String test = "Cats go meow"; 
     String[] tokens = pattern.split(test); 
    } 
} 
+1

Considerare anche la possibilità di rendere il pattern statico e definitivo.Essi farebbe risparmiare il sovraccarico di compilazione per ogni istanza – Rohit

3

No, penso che sarebbe una cattiva idea!

Guardando da vicino il codice sorgente dello split-metodo - c'è una scorciatoia implementato nel caso in cui la stringa è solo di un carattere (e non contiene un carattere regex-speciale)

public String[] split(String regex, int limit) { 
    /* fastpath if the regex is a 
    (1)one-char String and this character is not one of the 
     RegEx's meta characters ".$|()[{^?*+\\", or 
    (2)two-char String and the first char is the backslash and 
     the second is not the ascii digit or ascii letter. 
    */ 
    char ch = 0; 
    if (((regex.value.length == 1 && 
     ".$|()[{^?*+\\".indexOf(ch = regex.charAt(0)) == -1) || 

così - split ("") dovrebbe essere molto più veloce.

D'altra parte quando si usano espressioni regolari è sempre una buona idea renderli membri finali statici.

edit:

Il codice sorgente JDK1.7 e OpenJDK 7 sembra essere identico per String.split - Vai a vedere voi stessi: Lines 2312ff.

Così - per i modelli più complicati (1 o più spazi per esempio):

static final Pattern pSpaces = Pattern.compile("[ ]+"); 
+0

hmm Vorrei contestare che uno String.split all'interno di un ciclo while invalida questo reclamo. Cura di contrastare? – Woot4Moo

+0

Non capisco cosa intendi: che ciclo? –

+0

solo perché il mio programma non illustra un ciclo 'while' non significa che altri programmi non li abbiano. Se scrivessi un parser che doveva tokenizzare una serie di linee, ci sarebbe stato un ciclo 'while' – Woot4Moo