简体   繁体   中英

When would it be worth using RegEx in Java?

I'm writing a small app that reads some input and do something based on that input.

Currently I'm looking for a line that ends with, say, "magic", I would use String's endsWith method. It's pretty clear to whoever reads my code what's going on.

Another way to do it is create a Pattern and try to match a line that ends with "magic". This is also clear, but I personally think this is an overkill because the pattern I'm looking for is not complex at all.

When do you think it's worth using RegEx Java? If it's complexity, how would you personally define what's complex enough?

Also, are there times when using Patterns are actually faster than string manipulation?

EDIT: I'm using Java 6.

Basically: if there is a non-regex operation that does what you want in one step, always go for that.

This is not so much about performance, but about a) readability and b) compile-time-safety. Specialized non-regex versions are usually a lot easier to read than regex-versions. And a typo in one of these specialized methods will not compile, while a typo in a Regex will fail miserably at runtime.

Comparing Regex-based solutions to non-Regex-bases solutions

String s = "Magic_Carpet_Ride";

s.startsWith("Magic");   // non-regex
s.matches("Magic.*");    // regex

s.contains("Carpet");    // non-regex
s.matches(".*Carpet.*"); // regex

s.endsWith("Ride");      // non-regex
s.matches(".*Ride");     // regex

In all these cases it's a No-brainer: use the non-regex version.

But when things get a bit more complicated, it depends. I guess I'd still stick with non-regex in the following case, but many wouldn't:

// Test whether a string ends with "magic" in any case,
// followed by optional white space
s.toLowerCase().trim().endsWith("magic"); // non-regex, 3 calls
s.matches(".*(?i:magic)\\s*");            // regex, 1 call, but ugly

And in response to RegexesCanCertainlyBeEasierToReadThanMultipleFunctionCallsToDoTheSameThing :

I still think the non-regex version is more readable, but I would write it like this:

s.toLowerCase()
 .trim()
 .endsWith("magic");

Makes the whole difference, doesn't it?

You would use Regex when the normal manipulations on the String class are not enough to elegantly get what you need from the String.

A good indicator that this is the case is when you start splitting, then splitting those results, then splitting those results. The code is getting unwieldy. Two lines of Pattern/Regex code can clean this up, neatly wrapped in a method that is unit tested....

Anything that can be done with regex can also be hand-coded.

Use regex if:

  1. Doing it manually is going to take more effort without much benefit.
  2. You can easily come up with a regex for your task.

Don't use regex if:

  1. It's very easy to do it otherwise, as in your example.
  2. The string you're parsing does not lend itself to regex. (it is customary to link to this question )

I think you are best with using endsWith . Unless your requirements change, it's simpler and easier to understand. Might perform faster too.

If there was a bit more complexity, such as you wanted to match "magic", "majik', but not "Magic" or "Majik"; or you wanted to match "magic" followed by a space and then 1 word such as "... magic spoon" but not "...magic soup spoon", then I think RegEx would be a better way to go.

Any complex parsing where you are generating a lot of Objects would be better done with RegEx when you factor in both computing power, and brainpower it takes to generate the code for that purpose. If you have a RegEx guru handy, it's almost always worthwhile as the patterns can easily be tweaked to accommodate for business rule changes without major loop refactoring which would likely be needed if you used pure java to do some of the complex things RegEx does.

There's a saying that goes:

Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems . ( link ).

For a simple test, I'd proceed exactly like you've done. If you find that it's getting more complicated, then I'd consider Regular Expressions only if there isn't another way.

If your basic line ending is the same everytime, such as with "magic", then you are better of using endsWith.

However, if you have a line that has the same base, but can have multiple values, such as:

<string> <number> <string> <string> <number>

where the strings and numbers can be anything, you're better of using RegEx.

Your lines are always ending with a string, but you don't know what that string is.

If it's as simple as endsWith, startsWith or contains, then you should use these functions. If you are processing more "complex" strings and you want to extract information from these strings, then regexp/matchers can be used.

If you have something like "commandToRetrieve someNumericArgs someStringArgs someOptionalArgs" then regexp will ease your task a lot :)

I'd never use regexes in java if I have an easier way to do it, like in this case the endsWith method. Regexes in java are as ugly as they get, probably with the only exception of the match method on String .

Usually avoiding regexes makes your core more readable and easier for other programmers. The opposite is true, complex regexes might confuse even the most experience hackers out there.

As for performance concerns: just profile. Specially in java.

I would suggest using a regular expression when you know the format of an input but you are not necessarily sure on the value (or possible value(s)) of the formatted input.

What I'm saying, if you have an input all ending with, in your case, "magic" then String.endsWith() works fine (seeing you know that your possible input value will end with "magic").

If you have a format eg a RFC 5322 message format , one cannot clearly say that all email address can end with a .com , hence you can create a regular expression that conforms to the RFC 5322 standard for verification.

In a nutshell, if you know a format structure of your input data but don't know exactly what values (or possible values) you can receive, use regular expressions for validation.

If you are familiar with how regexp works you will soon find that a lot of problems are easily solved by using regexp.

Personally I look to using java String operations if that is easy, but if you start splitting strings and doing substring on those again, I'd start thinking in regular expressions.

And again, if you use regular expressions, why stop at lines. By configuring your regexp you can easily read entire files in one regular expression (Pattern.DOTALL as parameter to the Pattern.compile and your regexp don't end in the newlines). I'd combine this with Apache Commons IOUtils.toString() methods and you got something very powerful to do quick stuff with.

I would even bring out a regular expression to parse some xml if needed. (For instance in a unit test, where I want to check that some elements are present in the xml).

For instance, from some unit test of mine:

Pattern pattern = Pattern.compile(
                "<Monitor caption=\"(.+?)\".*?category=\"(.+?)\".*?>"
                + ".*?<Summary.*?>.+?</Summary>"
                + ".*?<Configuration.*?>(.+?)</Configuration>"
                + ".*?<CfgData.*?>(.+?)</CfgData>", Pattern.DOTALL);

which will match all segments in this xml and pick out some segments that I want to do some sub matching on.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM