Skip to content

Commit d6d8eff

Browse files
committed
Pre-compile the regex pattern into a Pattern object and reuse
1 parent 10be32c commit d6d8eff

3 files changed

Lines changed: 170 additions & 0 deletions

File tree

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package com.baeldung.pattern;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.Arrays;
6+
import java.util.List;
7+
import java.util.function.Predicate;
8+
import java.util.regex.Pattern;
9+
import java.util.stream.Collectors;
10+
11+
import static org.junit.Assert.assertFalse;
12+
import static org.junit.Assert.assertTrue;
13+
14+
public class PatternJava11UnitTest {
15+
16+
private static final String VALID_NAME = "Fabio Silva";
17+
private static final String INVALID_NAME = "Fabio Luis Silva";
18+
private static final List<String> NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME);
19+
private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}");
20+
21+
@Test
22+
public void givenPreCompiledPattern_whenCallAsMatchPredicate_thenReturnMatchPredicateToMatchesThePatternInTheListElements() {
23+
Predicate<String> patternAsMatchPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asMatchPredicate();
24+
List<String> validatedNames = NAMES_TO_VALIDATE.stream()
25+
.filter(patternAsMatchPredicate)
26+
.collect(Collectors.toList());
27+
28+
assertTrue(validatedNames.contains(VALID_NAME));
29+
assertFalse(validatedNames.contains(INVALID_NAME));
30+
}
31+
}
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
package com.baeldung.pattern;
2+
3+
import java.time.Duration;
4+
import java.time.Instant;
5+
import java.util.ArrayList;
6+
import java.util.List;
7+
import java.util.regex.Matcher;
8+
import java.util.regex.Pattern;
9+
10+
public class PatternPerformanceComparison {
11+
12+
private static final String PATTERN = "\\d*[02468]";
13+
private static List<String> values;
14+
15+
public static void main(String[] args) {
16+
loadValues();
17+
18+
// 5_000_000 Pattern objects created
19+
// 5_000_000 Matcher objects created
20+
Instant start = Instant.now();
21+
for (String value : values) {
22+
value.matches(PATTERN);
23+
}
24+
System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> String.matchs(regex)");
25+
26+
// Above approach "value.matches(PATTERN)" makes this internally
27+
// 5_000_000 Pattern objects created
28+
// 5_000_000 Matcher objects created
29+
start = Instant.now();
30+
for (String value : values) {
31+
Pattern.matches(PATTERN, value);
32+
}
33+
System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.matches(regex, charSequence)");
34+
35+
// Above approach "Pattern.matches(PATTERN, value)" makes this internally
36+
// 5_000_000 Pattern objects created
37+
// 5_000_000 Matcher objects created
38+
start = Instant.now();
39+
for (String value : values) {
40+
Pattern.compile(PATTERN).matcher(value).matches();
41+
}
42+
System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> Pattern.compile(regex).matcher(charSequence).matches()");
43+
44+
// With pre-compiled pattern
45+
// 1 Pattern object created
46+
// 5_000_000 Matcher objects created
47+
Pattern preCompiledPattern = Pattern.compile(PATTERN);
48+
start = Instant.now();
49+
for (String value : values) {
50+
preCompiledPattern.matcher(value).matches();
51+
}
52+
System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> preCompiledPattern.matcher(value).matches()");
53+
54+
//With pre-compiled pattern and reusing the matcher
55+
// 1 Pattern object created
56+
// 1 Matcher objects created
57+
Matcher matcherFromPreCompiledPattern = preCompiledPattern.matcher("");
58+
start = Instant.now();
59+
for (String value : values) {
60+
matcherFromPreCompiledPattern.reset(value).matches();
61+
}
62+
System.out.println(Duration.between(start, Instant.now()).toMillis() + "ms -> matcherFromPreCompiledPattern.reset(value).matches()");
63+
}
64+
65+
private static void loadValues() {
66+
values = new ArrayList<>();
67+
for (int x = 1; x <= 5_000_000; x++) {
68+
values.add(String.valueOf(x));
69+
}
70+
}
71+
}
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
package com.baeldung.pattern;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import java.util.Arrays;
6+
import java.util.List;
7+
import java.util.function.Predicate;
8+
import java.util.regex.Matcher;
9+
import java.util.regex.Pattern;
10+
import java.util.stream.Collectors;
11+
import java.util.stream.Stream;
12+
13+
import static org.junit.Assert.*;
14+
15+
public class PatternUnitTest {
16+
17+
private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}");
18+
private static final String VALID_NAME = "Fabio Silva";
19+
private static final String INVALID_NAME = "Mr. Silva";
20+
private static final List<String> NAMES_TO_VALIDATE = Arrays.asList(VALID_NAME, INVALID_NAME);
21+
22+
private static final Pattern SPLIT_PRE_COMPILED_PATTERN = Pattern.compile("__");
23+
private static final String TEXT_TO_SPLIT = "My_Name__is__Fabio_Silva";
24+
25+
@Test
26+
public void givenPreCompiledPattern_whenCallMatcher_thenReturnAMatcherToMatches() {
27+
Matcher matcherName1 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(VALID_NAME);
28+
Matcher matcherName2 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher(INVALID_NAME);
29+
30+
boolean matchesName1 = matcherName1.matches();
31+
boolean matchesName2 = matcherName2.matches();
32+
33+
assertTrue(matchesName1);
34+
assertFalse(matchesName2);
35+
}
36+
37+
@Test
38+
public void givenPreCompiledPattern_whenCallAsPredicate_thenReturnPredicateToFindThePatternInTheListElements() {
39+
Predicate<String> patternsAsPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asPredicate();
40+
41+
List<String> validNames = NAMES_TO_VALIDATE.stream()
42+
.filter(patternsAsPredicate)
43+
.collect(Collectors.toList());
44+
45+
assertEquals(1,validNames.size());
46+
assertTrue(validNames.contains(VALID_NAME));
47+
}
48+
49+
@Test
50+
public void givenPreCompiledPattern_whenCallSplit_thenReturnArrayWithValuesSplitByThePattern() {
51+
String[] textSplit = SPLIT_PRE_COMPILED_PATTERN.split(TEXT_TO_SPLIT);
52+
53+
assertEquals("My_Name", textSplit[0]);
54+
assertEquals("is", textSplit[1]);
55+
assertEquals("Fabio_Silva", textSplit[2]);
56+
}
57+
58+
@Test
59+
public void givenPreCompiledPattern_whenCallSplitAsStream_thenReturnArrayWithValuesSplitByThePattern() {
60+
Stream<String> textSplitAsStream = SPLIT_PRE_COMPILED_PATTERN.splitAsStream(TEXT_TO_SPLIT);
61+
String[] textSplit = textSplitAsStream.toArray(String[]::new);
62+
63+
assertEquals("My_Name", textSplit[0]);
64+
assertEquals("is", textSplit[1]);
65+
assertEquals("Fabio_Silva", textSplit[2]);
66+
}
67+
68+
}

0 commit comments

Comments
 (0)