diff --git a/java-strings-3/pom.xml b/java-strings-3/pom.xml
index 1e5f757943..4589780c15 100644
--- a/java-strings-3/pom.xml
+++ b/java-strings-3/pom.xml
@@ -68,6 +68,12 @@
${assertj.version}
test
+
+ org.bitbucket.cowwoc
+ diff-match-patch
+ 1.2
+ test
+
diff --git a/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffBenchmarkUnitTest.java b/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffBenchmarkUnitTest.java
new file mode 100644
index 0000000000..20e87a1f4e
--- /dev/null
+++ b/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffBenchmarkUnitTest.java
@@ -0,0 +1,73 @@
+package com.baeldung.stringdiff;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+
+import org.apache.commons.lang3.RandomStringUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bitbucket.cowwoc.diffmatchpatch.DiffMatchPatch;
+import org.openjdk.jmh.annotations.Benchmark;
+import org.openjdk.jmh.annotations.BenchmarkMode;
+import org.openjdk.jmh.annotations.Mode;
+import org.openjdk.jmh.annotations.OutputTimeUnit;
+import org.openjdk.jmh.annotations.Scope;
+import org.openjdk.jmh.annotations.State;
+import org.openjdk.jmh.runner.Runner;
+import org.openjdk.jmh.runner.RunnerException;
+import org.openjdk.jmh.runner.options.Options;
+import org.openjdk.jmh.runner.options.OptionsBuilder;
+
+@BenchmarkMode(Mode.AverageTime)
+@OutputTimeUnit(TimeUnit.MILLISECONDS)
+@State(Scope.Benchmark)
+public class StringDiffBenchmarkUnitTest {
+
+ private DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
+
+ private List inputs = randomizeInputs(10000);
+
+ public static void main(String[] args) throws RunnerException {
+ Options opts = new OptionsBuilder().include(".*")
+ .warmupIterations(1)
+ .measurementIterations(50)
+ .jvmArgs("-Xms2g", "-Xmx2g")
+ .shouldDoGC(true)
+ .forks(1)
+ .build();
+
+ new Runner(opts).run();
+ }
+
+ @Benchmark
+ public int diffMatchPatch() {
+ for (int i = 0; i < inputs.size() - 1; i++) {
+ diffMatchPatch.diffMain(inputs.get(i), inputs.get(i + 1), false);
+ }
+ return inputs.size();
+ }
+
+ @Benchmark
+ public int stringUtils() {
+ for (int i = 0; i < inputs.size() - 1; i++) {
+ StringUtils.difference(inputs.get(i), inputs.get(i + 1));
+ }
+ return inputs.size();
+ }
+
+ /**
+ * Creates a list of a given size, containing 30 character long strings,
+ * each starting with a static prefix of 10 characters and followed by
+ * a random 20 character suffix
+ *
+ * @return a {@link List} of randomised strings
+ */
+ private List randomizeInputs(int size) {
+ String staticPart = "ABCDEF1234";
+ List inputs = new ArrayList<>();
+ for (int i = 0; i < size; i++) {
+ inputs.add(staticPart + RandomStringUtils.randomAlphabetic(20));
+ }
+ return inputs;
+ }
+}
diff --git a/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffUnitTest.java b/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffUnitTest.java
new file mode 100644
index 0000000000..94b7deb64d
--- /dev/null
+++ b/java-strings-3/src/test/java/com/baeldung/stringdiff/StringDiffUnitTest.java
@@ -0,0 +1,39 @@
+package com.baeldung.stringdiff;
+
+import static org.hamcrest.Matchers.containsInAnyOrder;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+import org.apache.commons.lang3.StringUtils;
+import org.bitbucket.cowwoc.diffmatchpatch.DiffMatchPatch;
+import org.bitbucket.cowwoc.diffmatchpatch.DiffMatchPatch.Operation;
+import org.junit.Test;
+
+public class StringDiffUnitTest {
+
+ private DiffMatchPatch diffMatchPatch = new DiffMatchPatch();
+
+ // Test samples
+ private final String text1 = "ABCDELMN";
+ private final String text2 = "ABCFGLMN";
+
+ @Test
+ public void givenTwoStrings_whenDiffMatchPatch_thenReturnCorrectDiff() {
+ assertThat(diffMatchPatch.diffMain(text1, text2, false), containsInAnyOrder(
+ new DiffMatchPatch.Diff(Operation.EQUAL, "ABC"),
+ new DiffMatchPatch.Diff(Operation.DELETE, "DE"),
+ new DiffMatchPatch.Diff(Operation.INSERT, "FG"),
+ new DiffMatchPatch.Diff(Operation.EQUAL, "LMN")));
+ assertThat(diffMatchPatch.diffMain(text2, text1, false), containsInAnyOrder(
+ new DiffMatchPatch.Diff(Operation.EQUAL, "ABC"),
+ new DiffMatchPatch.Diff(Operation.INSERT, "DE"),
+ new DiffMatchPatch.Diff(Operation.DELETE, "FG"),
+ new DiffMatchPatch.Diff(Operation.EQUAL, "LMN")));
+ }
+
+ @Test
+ public void givenTwoStrings_whenStringUtilsDifference_thenReturnCorrectDiff() {
+ assertThat(StringUtils.difference(text1, text2), is("FGLMN"));
+ assertThat(StringUtils.difference(text2, text1), is("DELMN"));
+ }
+}