1

I heavily use regular expressions to store business parameters in various tables (primarily business decision-tree logic). When thousands of business objects attempt to match themselves to these regex-driven parameters, it can be quite slow using the String.matches() on various properties. So I created a class called MatchRegex which acts as a property type over a regex String, and it internally compiles the regex and resets the test input Strings.

public final class MatchRegex {
    private final String regex;
    private final Pattern pattern;
    private final Matcher matcher;

    private MatchRegex(String regex) { 
        this.regex = regex;
        this.pattern = Pattern.compile(regex);
        this.matcher = pattern.matcher("Hello");
    }
    public static MatchRegex of(String regex) { 
        return new MatchRegex(regex);
    }
    public boolean matches(String input) { 
        return matcher.reset(input).matches();
    }
    public String getRegex() { 
        return regex;
    }
}

However, I'm a bit disturbed I randomly get an error that makes little sense to me unless I dig into the Pattern source code. It fails on the return matcher.reset(input).matches() line. Is this a bug with the regex library? How do i fix it?

java.lang.StringIndexOutOfBoundsException: String index out of range: 7
    at java.lang.String.charAt(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Pattern$GroupTail.match(Unknown Source)
    at java.util.regex.Pattern$BranchConn.match(Unknown Source)
    at java.util.regex.Pattern$Slice.match(Unknown Source)
    at java.util.regex.Pattern$Branch.match(Unknown Source)
    at java.util.regex.Pattern$GroupHead.match(Unknown Source)
    at java.util.regex.Pattern$GroupTail.match(Unknown Source)
    at java.util.regex.Pattern$BranchConn.match(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Pattern$Branch.match(Unknown Source)
    at java.util.regex.Pattern$GroupHead.match(Unknown Source)
    at java.util.regex.Pattern$BmpCharProperty.match(Unknown Source)
    at java.util.regex.Matcher.match(Unknown Source)
    at java.util.regex.Matcher.matches(Unknown Source)
3
  • 2
    Are you using this from multiple threads? (Pattern is thread-safe; Matcher isn't.) Commented Apr 9, 2015 at 14:38
  • I just had that realization the moment you commented. Commented Apr 9, 2015 at 14:38
  • Dang it, so now I have to either synchronize or make Matcher thread-local. I'd hate to make it more expensive. Commented Apr 9, 2015 at 14:40

1 Answer 1

1

Just realized the same moment as Jon Skeet that Matcher is not threadsafe. I will need to use some thread localization or synchronization. Hopefully it will not cost too much in performance.

UPDATE I am guessing the most efficient strategy is to just invoke a new Matcher each time.

public final class MatchRegex {
    private final String regex;
    private final Pattern pattern;

    private MatchRegex(String regex) { 
        this.regex = regex;
        this.pattern = Pattern.compile(regex);
    }
    public static MatchRegex of(String regex) { 
        return new MatchRegex(regex);
    }
    public boolean matches(String input) { 
        return pattern.matcher(input).matches();
    }
    public String getRegex() { 
        return regex;
    }
}
Sign up to request clarification or add additional context in comments.

5 Comments

Or find a way not to share the MatchRegex objects.
That's going to be a bit challenging. Each business object (maintained in a singleton collection corresponding to a database table) uses MatchRegex as a type for the object properties. the MatchRegex is an inherent part of the object's identity from a business perspective.
I think I'll just have to supply a new Matcher each time off the compiled Pattern, as shown in my update above.
Eclipse is telling me that constructor is not visible... hmmm.
Ooops my bad - forget that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.