2013-03-05 12 views
5

Sto cercando di migliorare le prestazioni di alcuni codici. Sembra qualcosa di simile:Come determinare se una stringa non è un'espressione regolare?

public boolean isImportant(String token) { 
    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    } 
} 

Quello che ho notato è che molti dei modelli sembrano essere semplici stringhe letterali senza costrutti di espressione regolari. Quindi voglio archiviare semplicemente questi in un elenco separato (importantList) e fare un test di uguaglianza invece di eseguire un pattern match più costosi, come ad esempio segue:

public boolean isImportant(String token) { 
    if (importantList.contains(token)) return true; 

    for (Pattern pattern : patterns) { 
     return pattern.matches(token).find(); 
    }   
} 

Come faccio a livello di programmazione determinare se una particolare stringa non contiene costrutti di espressione regolare?

Modifica: Devo aggiungere che la risposta non deve essere sensibile alle prestazioni. (Ad esempio, le espressioni regolari possono essere utilizzate) Mi interesso principalmente delle prestazioni di isImportant() perché è chiamato milioni di volte, mentre l'inizializzazione dei pattern viene eseguita una sola volta.

+1

Non eseguire un'espressione regolare su una stringa per determinare se si tratta di un'espressione regolare ogni volta è molto peggio che utilizzare ogni stringa come espressione regolare? –

+3

@ Mike: Non è quello che sta chiedendo. "ciao" è un'espressione regolare perfettamente valida. –

+0

Non possibile (non è facile né utile, a meno che non si trovi qualche schema in normali stringhe di stringa). Una semplice stringa letterale è un modello di regex valido. – AC1

risposta

3

Sarà difficile. È possibile verificare la non presenza di eventuali metacaratteri regex; che dovrebbe essere una buona approssimazione:

Pattern regex = Pattern.compile("[$^()\\[\\]{}.*+?\\\\]"); 
Matcher regexMatcher = regex.matcher(subjectString); 
regexIsLikely = regexMatcher.find(); 

Se vale la pena è un'altra domanda. Sei sicuro che una regex match sia più lenta di una ricerca in lista (specialmente visto che in seguito dovrai eseguire una regex match in molti casi)? Scommetto che è molto più veloce mantenere la corrispondenza regex.

+0

Questa è la soluzione con cui sono andato. È interessante notare che ho ridotto i tempi di elaborazione di circa il 50%. –

4

Di solito odio le risposte che dicono questo, ma ...

non lo faccio.

Probabilmente non eseguirà il codice più velocemente, anzi potrebbe addirittura richiedere più tempo al programma.

se hai davvero bisogno di ottimizzare il tuo codice, ci sono probabilmente molti posti molto più efficaci dove puoi andare.

+0

Intendo che il profiler risponda alla domanda se le ottimizzazioni siano significative o meno. –

2

Non esiste alcun modo per determinarlo poiché ogni schema di espressioni regolari non è altro che una stringa. Inoltre v'è quasi alcuna differenza di prestazioni come espressione regolare è intelligente al giorno d'oggi e sono abbastanza sicuro che, se le lunghezze del modello e di origine sono la stessa cosa, controllo equità è il primo che sarà fatto

+1

Dipende, ma stimerei che Java tenti di eseguire la regex DFA molto più efficiente e scambia solo NFA se l'espressione lo richiede (ad esempio se include il lookaround) –

1

Questo è sbagliato

for (Pattern pattern : patterns) 

si dovrebbe creare una regex grande che OR tutti i modelli; quindi per ciascun ingresso si combina solo una volta.

+0

Grazie. In realtà l'ho fatto e ho scoperto che l'uso di un modello gigante era circa 1/3 più veloce rispetto a più modelli piccoli. –

Problemi correlati