~/home of geeks

Regex Caching

· 243 Wörter · 2 Minute(n) Lesedauer

Dieser Artikel ist Teil der Artikel-Serie "kurz notiert".

Häufig benutzt: reguläre Ausdrücke in Java. Jedoch ist das Neu instanziieren eines Patterns / Matchers zeitintensiv. Ein einfaches Caching auf Basis von ThreadLocal hilft hier, die nicht-threadsafen Matcher zu cachen.

Doch Vorsicht: ThreadLocals können Memoryleaks erzeugen, wenn das ThreadLocal nicht aufgeräumt wird.

public class RegexUtils {
    private static ThreadLocal<Map<String, Matcher>> CASESENSITIVE_MATCHER_CACHE =
            new ThreadLocal<Map<String, Matcher>>() {
                protected Map<String, Matcher> initialValue() {
                    return new HashMap<String, Matcher>();
                }
            };

    private static ThreadLocal<Map<String, Matcher>> CASEINSENSITIVE_MATCHER_CACHE =
            new ThreadLocal<Map<String, Matcher>>() {
                protected Map<String, Matcher> initialValue() {
                    return new HashMap<String, Matcher>();
                }
            };

    public static boolean containsIgnoreCase(String text, String regex) {
        if (text == null || text.length() < 1) {
            return false;
        }
        Matcher m = CASEINSENSITIVE_MATCHER_CACHE.get().get(regex);
        if (m == null) {
            m = Pattern.compile(regex, Pattern.CANON_EQ |
                    Pattern.CASE_INSENSITIVE | Pattern.DOTALL |
                    Pattern.MULTILINE).matcher("");
            CASEINSENSITIVE_MATCHER_CACHE.get().put(regex, m);
        }
        return m.reset(text).find();
    }

    public static boolean contains(String text, String regex) {
        if (text == null || text.length() < 1) {
            return false;
        }
        Matcher m = CASESENSITIVE_MATCHER_CACHE.get().get(regex);
        if (m == null) {
            m = Pattern.compile(regex, Pattern.CANON_EQ |
                    Pattern.DOTALL | Pattern.MULTILINE).matcher("");
            CASESENSITIVE_MATCHER_CACHE.get().put(regex, m);
        }
        return m.reset(text).find();
    }

    public static final Matcher getCaseinsensitiveMatcher(String text, String regex) {
        Matcher m = CASEINSENSITIVE_MATCHER_CACHE.get().get(regex);
        if (m == null) {
            m = Pattern.compile(regex, Pattern.CANON_EQ |
                    Pattern.CASE_INSENSITIVE | Pattern.DOTALL |
                    Pattern.MULTILINE).matcher("");
            CASEINSENSITIVE_MATCHER_CACHE.get().put(regex, m);
        }
        return m.reset(text);
    }

    public static final Matcher getCasesensitiveMatcher(String text, String regex) {
        Matcher m = CASESENSITIVE_MATCHER_CACHE.get().get(regex);
        if (m == null) {
            m = Pattern.compile(regex, Pattern.CANON_EQ |
                    Pattern.DOTALL |
                    Pattern.MULTILINE).matcher("");
            CASESENSITIVE_MATCHER_CACHE.get().put(regex, m);
        }
        return m.reset(text);
    }
}