Merge pull request #8321 from silvafabio/master

Pre-compile the regex pattern into a Pattern object and reuse
This commit is contained in:
rpvilao 2019-12-20 15:28:11 +01:00 committed by GitHub
commit 02f52d9b98
4 changed files with 197 additions and 0 deletions

View File

@ -0,0 +1,29 @@
package com.baeldung.patternreuse;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
public class PatternJava11UnitTest {
@Test
public void givenPreCompiledPattern_whenCallAsMatchPredicate_thenReturnMatchPredicateToMatchesThePatternInTheListElements() {
List<String> namesToValidate = Arrays.asList("Fabio Silva", "Fabio Luis Silva");
Pattern firstLastNamePreCompiledPattern = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}");
Predicate<String> patternAsMatchPredicate = firstLastNamePreCompiledPattern.asMatchPredicate();
List<String> validatedNames = namesToValidate.stream()
.filter(patternAsMatchPredicate)
.collect(Collectors.toList());
assertTrue(validatedNames.contains("Fabio Silva"));
assertFalse(validatedNames.contains("Fabio Luis Silva"));
}
}

View File

@ -14,6 +14,19 @@
<relativePath>../../parent-java</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-core</artifactId>
<version>${jmh-core.version}</version>
</dependency>
<dependency>
<groupId>org.openjdk.jmh</groupId>
<artifactId>jmh-generator-annprocess</artifactId>
<version>${jmh-core.version}</version>
</dependency>
</dependencies>
<build>
<finalName>core-java-text</finalName>
<resources>

View File

@ -0,0 +1,92 @@
package com.baeldung.patternreuse;
import org.openjdk.jmh.annotations.*;
import org.openjdk.jmh.infra.Blackhole;
import org.openjdk.jmh.runner.RunnerException;
import java.io.IOException;
import java.time.Instant;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MILLISECONDS)
@Fork(value = 1, warmups = 1)
@Warmup(iterations = 5)
@State(Scope.Benchmark)
public class PatternPerformanceComparison {
private static final String PATTERN = "\\d*[02468]";
private static List<String> values;
private static Matcher matcherFromPreCompiledPattern;
private static Pattern preCompiledPattern;
public static void main(String[] args) throws IOException, RunnerException {
org.openjdk.jmh.Main.main(args);
}
@Benchmark
public void matcherFromPreCompiledPatternResetMatches(Blackhole bh) {
//With pre-compiled pattern and reusing the matcher
// 1 Pattern object created
// 1 Matcher objects created
for (String value : values) {
bh.consume(matcherFromPreCompiledPattern.reset(value).matches());
}
}
@Benchmark
public void preCompiledPatternMatcherMatches(Blackhole bh) {
// With pre-compiled pattern
// 1 Pattern object created
// 5_000_000 Matcher objects created
for (String value : values) {
bh.consume(preCompiledPattern.matcher(value).matches());
}
}
@Benchmark
public void patternCompileMatcherMatches(Blackhole bh) {
// Above approach "Pattern.matches(PATTERN, value)" makes this internally
// 5_000_000 Pattern objects created
// 5_000_000 Matcher objects created
for (String value : values) {
bh.consume(Pattern.compile(PATTERN).matcher(value).matches());
}
}
@Benchmark
public void patternMatches(Blackhole bh) {
// Above approach "value.matches(PATTERN)" makes this internally
// 5_000_000 Pattern objects created
// 5_000_000 Matcher objects created
for (String value : values) {
bh.consume(Pattern.matches(PATTERN, value));
}
}
@Benchmark
public void stringMatchs(Blackhole bh) {
// 5_000_000 Pattern objects created
// 5_000_000 Matcher objects created
Instant start = Instant.now();
for (String value : values) {
bh.consume(value.matches(PATTERN));
}
}
@Setup()
public void setUp() {
preCompiledPattern = Pattern.compile(PATTERN);
matcherFromPreCompiledPattern = preCompiledPattern.matcher("");
values = new ArrayList<>();
for (int x = 1; x <= 5_000_000; x++) {
values.add(String.valueOf(x));
}
}
}

View File

@ -0,0 +1,63 @@
package com.baeldung.patternreuse;
import org.junit.jupiter.api.Test;
import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.*;
public class PatternUnitTest {
private static final Pattern FIRST_LAST_NAME_PRE_COMPILED_PATTERN = Pattern.compile("[a-zA-Z]{3,} [a-zA-Z]{3,}");
private static final Pattern SPLIT_PRE_COMPILED_PATTERN = Pattern.compile("__");
@Test
public void givenPreCompiledPattern_whenCallMatcher_thenReturnAMatcherToMatches() {
Matcher matcherName1 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher("Fabio Silva");
Matcher matcherName2 = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.matcher("Mr. Silva");
boolean matchesName1 = matcherName1.matches();
boolean matchesName2 = matcherName2.matches();
assertTrue(matchesName1);
assertFalse(matchesName2);
}
@Test
public void givenPreCompiledPattern_whenCallAsPredicate_thenReturnPredicateToFindThePatternInTheListElements() {
List<String> namesToValidate = Arrays.asList("Fabio Silva", "Mr. Silva");
Predicate<String> patternsAsPredicate = FIRST_LAST_NAME_PRE_COMPILED_PATTERN.asPredicate();
List<String> validNames = namesToValidate.stream()
.filter(patternsAsPredicate)
.collect(Collectors.toList());
assertEquals(1, validNames.size());
assertTrue(validNames.contains("Fabio Silva"));
}
@Test
public void givenPreCompiledPattern_whenCallSplit_thenReturnArrayWithValuesSplitByThePattern() {
String[] textSplit = SPLIT_PRE_COMPILED_PATTERN.split("My_Name__is__Fabio_Silva");
assertEquals("My_Name", textSplit[0]);
assertEquals("is", textSplit[1]);
assertEquals("Fabio_Silva", textSplit[2]);
}
@Test
public void givenPreCompiledPattern_whenCallSplitAsStream_thenReturnArrayWithValuesSplitByThePattern() {
Stream<String> textSplitAsStream = SPLIT_PRE_COMPILED_PATTERN.splitAsStream("My_Name__is__Fabio_Silva");
String[] textSplit = textSplitAsStream.toArray(String[]::new);
assertEquals("My_Name", textSplit[0]);
assertEquals("is", textSplit[1]);
assertEquals("Fabio_Silva", textSplit[2]);
}
}