Reputation: 313
I have two possibilities, make a regex or make a if compare.
If Compares
if (!(modoImpressao.equals("IMPRESSORA") ||
modoImpressao.equals("PDF") || modoImpressao.equals("AMBOS")))
Regex Match
if (!Pattern.compile("(IMPRESSORA)|(PDF)|(AMBOS)",Pattern.DOTALL).matcher(modoImpressao).find()){
throw new EspdNeverStopParametroInvalidoException(TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,"TspdImprimirNFCe");
}
which one is faster?
Upvotes: 12
Views: 10188
Reputation: 301
If you want to find pattern strings, rather than checking for equality (like your second code snippet does), performance may benefit from advanced string finding algorithms like Boyer-Moore-Horspool. While not trivial to implement on your own, many regex libraries (including java.util.regex) have it built in, so the search with the regex may be (much) faster in this case.
If „find()” speed is your major concern, you may also look into github.com/aunkrig/lfr .
Upvotes: 0
Reputation: 301
Starting with Java 7, you can use „string switches“, which are superfast because they’re based on the string’s hashes.
Upvotes: 0
Reputation: 21
Regex is faster for large string than an if (perhaps in a for loops) to check if anything matches your requirement.
If you are using regex as to match very small text and small pattern and don't do it because the matcher function .find() is slower than a normal if statement of a switch statement.
Upvotes: 2
Reputation: 298153
If you use the regular expression only one time, it’s likely to be slower, especially when you use find
where you actually mean matches
as in your question.
When you keep the compiled Pattern
and use it several times, it has the potential to be faster than multiple equals.
This, however, depends on the context. If all String
s you are testing are literals and matches are more likely than fails, String.equals
will be much faster as it circuits the test if the instances are the same.
The fastest solution is to preselect based on an easy-to-check property of the candidate String
s which is different for all String
s, e.g. a char
at a certain position or the length
, and perform a single equals
for the selected String
. In your case both, the first character and the length are appropriate. In this case I prefer length as you have to check the length anyway before accessing a character to protect against empty Strings
:
The preferred variant using length
:
nomatch:
{
switch(modoImpressao.length())
{
case 3: if(modoImpressao.equals("PDF")) break nomatch; break;
case 5: if(modoImpressao.equals("AMBOS")) break nomatch; break;
case 10: if(modoImpressao.equals("IMPRESSORA")) break nomatch; break;
}
throw new EspdNeverStopParametroInvalidoException(
TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,
"TspdImprimirNFCe");
}
// one of the three values matched
The variant using the first char
:
nomatch:
{
if(modoImpressao.length()>0) switch(modoImpressao.charAt(0))
{
case 'P': if(modoImpressao.equals("PDF")) break nomatch; break;
case 'A': if(modoImpressao.equals("AMBOS")) break nomatch; break;
case 'I': if(modoImpressao.equals("IMPRESSORA")) break nomatch; break;
}
throw new EspdNeverStopParametroInvalidoException(TspdConstMessages.IMPRIMIR_PARAMETRO_MODOIMPRESSAO_INVALIDO,"TspdImprimirNFCe");
}
// one of the three values matched
Upvotes: 3
Reputation: 129507
The first snippet will almost certainly be faster, since it doesn't have to parse a regular expression and perform a match against it. Another alternative is:
if (Arrays.asList("IMPRESSORA", "PDF", "AMBOS").contains(modoImpressao)
which shouldn't differ speed-wise much from your first snippet, but is arguably more readable and concise.
Regular expressions are great, but only use them when you need to. This situation definitely doesn't warrant the use of regexes; all you're doing is comparing against literal strings.
There's an old saying by Jamie Zawinski that goes like this:
Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems.
Upvotes: 19