From 54582f10f7499647f924b907fe7c4c8aba3945f1 Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Wed, 15 Jan 2020 00:20:15 +0100 Subject: [PATCH 1/8] Fix one of the tests modifying "," by "." --- .../stringconcatenation/StringConcatenationUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java index 9a444e8229..6d8d2eee3c 100644 --- a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java +++ b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java @@ -43,7 +43,7 @@ public class StringConcatenationUnitTest { "oops"); - assertEquals("I ate 2.51 blueberry pies, oops...", myString); + assertEquals("I ate 2,51 blueberry pies, oops...", myString); } @Test From 69a029f4ed8be880670a0eec2b1a292cd4025101 Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Wed, 15 Jan 2020 00:21:50 +0100 Subject: [PATCH 2/8] Add JMH dependency and shade the jar. Include examples to avoid contains() case insensitive behavior --- .../core-java-string-operations-2/pom.xml | 40 ++++++++- .../ContainsWorkarounds.java | 84 +++++++++++++++++++ 2 files changed, 122 insertions(+), 2 deletions(-) create mode 100644 core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java diff --git a/core-java-modules/core-java-string-operations-2/pom.xml b/core-java-modules/core-java-string-operations-2/pom.xml index bd1a34f89f..7bb687ea2b 100644 --- a/core-java-modules/core-java-string-operations-2/pom.xml +++ b/core-java-modules/core-java-string-operations-2/pom.xml @@ -1,6 +1,7 @@ - + 4.0.0 core-java-string-operations-2 0.1.0-SNAPSHOT @@ -51,6 +52,18 @@ ${org.hamcrest.version} test + + org.openjdk.jmh + jmh-core + ${jmh-core.version} + + + + org.openjdk.jmh + jmh-generator-annprocess + ${jmh-generator.version} + + org.assertj assertj-core @@ -61,6 +74,29 @@ core-java-string-operations-2 + + + org.apache.maven.plugins + maven-shade-plugin + 3.2.0 + + + package + + shade + + + + + org.openjdk.jmh.Main + + + + + + + src/main/resources diff --git a/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java new file mode 100644 index 0000000000..75150f6edb --- /dev/null +++ b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java @@ -0,0 +1,84 @@ +package com.baeldung.containscaseinsensitive; + +import java.util.concurrent.TimeUnit; +import java.util.regex.Pattern; + +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; + +/** + * Based on https://github.com/tedyoung/indexof-contains-benchmark + */ +@Fork(5) +@State(Scope.Benchmark) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.NANOSECONDS) +public class ContainsWorkarounds { + + private String src; + private String dest; + private Pattern pattern; + + public static void main(String[] args) throws Exception { + org.openjdk.jmh.Main.main(args); + } + + @Setup + public void setup() { + src = "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum"; + dest = "eiusmod"; + pattern = Pattern.compile(Pattern.quote(dest), Pattern.CASE_INSENSITIVE); + } + + // toLowerCase() and contains() + @Benchmark + public boolean lowerCaseContains() { + return src.toLowerCase() + .contains(dest.toLowerCase()); + } + + // matches() with Regular Expressions + @Benchmark + public boolean matchesRegularExpression() { + return src.matches("(?i).*" + dest + ".*"); + } + + // String regionMatches() + @Benchmark + public boolean regionMatches() { + + final char firstLo = Character.toLowerCase(dest.charAt(0)); + final char firstUp = Character.toUpperCase(dest.charAt(0)); + + for (int i = src.length() - dest.length(); i >= 0; i--) { + final char ch = src.charAt(i); + if (ch != firstLo && ch != firstUp) + continue; + + if (src.regionMatches(true, i, dest, 0, dest.length())) + return true; + } + + return false; + } + + // Pattern CASE_INSENSITIVE with regexp + @Benchmark + public boolean patternCaseInsensitiveRegexp() { + return pattern.matcher(src) + .find(); + } + + // Apache Commons StringUtils containsIgnoreCase + @Benchmark + public boolean apacheCommonsStringUtils() { + return org.apache.commons.lang3.StringUtils.containsIgnoreCase(src, dest); + } + +} From aac0d3598f6dec91a79d03ba55332879ddaff7f2 Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Wed, 15 Jan 2020 00:29:44 +0100 Subject: [PATCH 3/8] Update README file --- core-java-modules/core-java-string-operations-2/README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/core-java-modules/core-java-string-operations-2/README.md b/core-java-modules/core-java-string-operations-2/README.md index 50f40ac2af..6e88eda122 100644 --- a/core-java-modules/core-java-string-operations-2/README.md +++ b/core-java-modules/core-java-string-operations-2/README.md @@ -8,4 +8,5 @@ This module contains articles about string operations. - [String Initialization in Java](https://www.baeldung.com/java-string-initialization) - [String toLowerCase and toUpperCase Methods in Java](https://www.baeldung.com/java-string-convert-case) - [Java String equalsIgnoreCase()](https://www.baeldung.com/java-string-equalsignorecase) +- [How to avoid String contains() Case Insensitive in Java](https://www.baeldung.com/how-to-avoid-string-contains-case-insensitive-in-java) - More articles: [[<-- prev]](../core-java-string-operations) From 632f6d6c9ef3ac04d59c7b7885c28e39dfd61695 Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Wed, 15 Jan 2020 00:37:13 +0100 Subject: [PATCH 4/8] Undo the test fixing because is a wrong behavior in Windows --- .../stringconcatenation/StringConcatenationUnitTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java index 6d8d2eee3c..9a444e8229 100644 --- a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java +++ b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/stringconcatenation/StringConcatenationUnitTest.java @@ -43,7 +43,7 @@ public class StringConcatenationUnitTest { "oops"); - assertEquals("I ate 2,51 blueberry pies, oops...", myString); + assertEquals("I ate 2.51 blueberry pies, oops...", myString); } @Test From 6ba82d38ccce0ceae3f5fa6bbf6091e8fd89441c Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Mon, 27 Jan 2020 13:01:50 +0100 Subject: [PATCH 5/8] Rename the class to separate functionality from what the class is about --- .../CaseInsensitiveWorkarounds.java} | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) rename core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/{containscaseinsensitive/ContainsWorkarounds.java => contains/CaseInsensitiveWorkarounds.java} (79%) diff --git a/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java similarity index 79% rename from core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java rename to core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java index 75150f6edb..5965c6eb4f 100644 --- a/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/containscaseinsensitive/ContainsWorkarounds.java +++ b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java @@ -1,4 +1,4 @@ -package com.baeldung.containscaseinsensitive; +package com.baeldung.contains; import java.util.concurrent.TimeUnit; import java.util.regex.Pattern; @@ -19,7 +19,7 @@ import org.openjdk.jmh.annotations.State; @State(Scope.Benchmark) @BenchmarkMode(Mode.AverageTime) @OutputTimeUnit(TimeUnit.NANOSECONDS) -public class ContainsWorkarounds { +public class CaseInsensitiveWorkarounds { private String src; private String dest; @@ -49,23 +49,26 @@ public class ContainsWorkarounds { return src.matches("(?i).*" + dest + ".*"); } - // String regionMatches() - @Benchmark - public boolean regionMatches() { + public boolean processRegionMatches(String localSrc, String localDest) { + final char firstLo = Character.toLowerCase(localDest.charAt(0)); + final char firstUp = Character.toUpperCase(localDest.charAt(0)); - final char firstLo = Character.toLowerCase(dest.charAt(0)); - final char firstUp = Character.toUpperCase(dest.charAt(0)); - - for (int i = src.length() - dest.length(); i >= 0; i--) { - final char ch = src.charAt(i); + for (int i = localSrc.length() - localDest.length(); i >= 0; i--) { + final char ch = localSrc.charAt(i); if (ch != firstLo && ch != firstUp) continue; - if (src.regionMatches(true, i, dest, 0, dest.length())) + if (localSrc.regionMatches(true, i, localDest, 0, localDest.length())) return true; } - return false; + return false; + } + + // String regionMatches() + @Benchmark + public boolean regionMatches() { + return processRegionMatches(src, dest); } // Pattern CASE_INSENSITIVE with regexp From 0e116c9dfbae4a271b6478895daa17669228eaa4 Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Mon, 27 Jan 2020 13:02:25 +0100 Subject: [PATCH 6/8] Add unit tests for Case Insensitive Contains workarounds --- .../CaseInsensitiveWorkaroundsUnitTest.java | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java diff --git a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java new file mode 100644 index 0000000000..5e76bf0da3 --- /dev/null +++ b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java @@ -0,0 +1,53 @@ +package com.baeldung.contains; + +import org.apache.commons.lang3.StringUtils; +import org.junit.Assert; +import org.junit.Test; + +import java.util.regex.Pattern; + +/** + * BAEL-3739: Different ways to solve the contains() case insensitive behavior. + */ +public class CaseInsensitiveWorkaroundsUnitTest { + + private String src = "Lorem ipsum dolor sit amet"; + private String dest = "lorem"; + + @Test + public void givenString_whenCallingContainsWithToLowerOrUpperCase_shouldReturnTrue() { + // Use toLowerCase to avoid case insensitive issues + Assert.assertTrue(src.toLowerCase().contains(dest.toLowerCase())); + + // Use toUpperCase to avoid case insensitive issues + Assert.assertTrue(src.toUpperCase().contains(dest.toUpperCase())); + } + + @Test + public void givenString_whenCallingStringMatches_shouldReturnTrue() { + // Use String Matches to avoid case insensitive issues + Assert.assertTrue(src.matches("(?i).*" + dest + ".*")); + } + + @Test + public void givenString_whenCallingStringRegionMatches_shouldReturnTrue() { + // Use String Region Matches to avoid case insensitive issues + CaseInsensitiveWorkarounds comparator = new CaseInsensitiveWorkarounds(); + Assert.assertTrue(comparator.processRegionMatches(src, dest)); + } + + + @Test + public void givenString_whenCallingPaternCompileMatcherFind_shouldReturnTrue() { + // Use Pattern Compile Matcher and Find to avoid case insensitive issues + Assert.assertTrue(Pattern.compile(Pattern.quote(dest), + Pattern.CASE_INSENSITIVE) .matcher(src) .find()); + } + + @Test + public void givenString_whenCallingStringUtilsContainsIgnoreCase_shouldReturnTrue() { + // Use StringUtils containsIgnoreCase to avoid case insensitive issues + Assert.assertTrue(StringUtils.containsIgnoreCase(src, dest)); + } + +} \ No newline at end of file From 8ecc31f99e18a1ba99b1606cbfaf66cb8b67ba1d Mon Sep 17 00:00:00 2001 From: Cavero Barca Date: Mon, 27 Jan 2020 14:09:58 +0100 Subject: [PATCH 7/8] Add a refinement for clarity in the RegionMatches function --- .../baeldung/contains/CaseInsensitiveWorkarounds.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java index 5965c6eb4f..e4089a4f53 100644 --- a/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java +++ b/core-java-modules/core-java-string-operations-2/src/main/java/com/baeldung/contains/CaseInsensitiveWorkarounds.java @@ -50,18 +50,9 @@ public class CaseInsensitiveWorkarounds { } public boolean processRegionMatches(String localSrc, String localDest) { - final char firstLo = Character.toLowerCase(localDest.charAt(0)); - final char firstUp = Character.toUpperCase(localDest.charAt(0)); - - for (int i = localSrc.length() - localDest.length(); i >= 0; i--) { - final char ch = localSrc.charAt(i); - if (ch != firstLo && ch != firstUp) - continue; - + for (int i = localSrc.length() - localDest.length(); i >= 0; i--) if (localSrc.regionMatches(true, i, localDest, 0, localDest.length())) return true; - } - return false; } From cffbc130ecc8008bde2997c1140c076ccd5b50e4 Mon Sep 17 00:00:00 2001 From: Carlos Cavero Date: Tue, 4 Feb 2020 10:20:14 +0100 Subject: [PATCH 8/8] Modify "then" by "should" in the Unit Tests as suggested from code review Co-Authored-By: KevinGilmore --- .../contains/CaseInsensitiveWorkaroundsUnitTest.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java index 5e76bf0da3..30b2ca9fa5 100644 --- a/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java +++ b/core-java-modules/core-java-string-operations-2/src/test/java/com/baeldung/contains/CaseInsensitiveWorkaroundsUnitTest.java @@ -24,13 +24,13 @@ public class CaseInsensitiveWorkaroundsUnitTest { } @Test - public void givenString_whenCallingStringMatches_shouldReturnTrue() { + public void givenString_whenCallingStringMatches_thenReturnsTrue() { // Use String Matches to avoid case insensitive issues Assert.assertTrue(src.matches("(?i).*" + dest + ".*")); } @Test - public void givenString_whenCallingStringRegionMatches_shouldReturnTrue() { + public void givenString_whenCallingStringRegionMatches_thenReturnsTrue() { // Use String Region Matches to avoid case insensitive issues CaseInsensitiveWorkarounds comparator = new CaseInsensitiveWorkarounds(); Assert.assertTrue(comparator.processRegionMatches(src, dest)); @@ -38,16 +38,16 @@ public class CaseInsensitiveWorkaroundsUnitTest { @Test - public void givenString_whenCallingPaternCompileMatcherFind_shouldReturnTrue() { + public void givenString_whenCallingPaternCompileMatcherFind_thenReturnsTrue() { // Use Pattern Compile Matcher and Find to avoid case insensitive issues Assert.assertTrue(Pattern.compile(Pattern.quote(dest), Pattern.CASE_INSENSITIVE) .matcher(src) .find()); } @Test - public void givenString_whenCallingStringUtilsContainsIgnoreCase_shouldReturnTrue() { + public void givenString_whenCallingStringUtilsContainsIgnoreCase_thenReturnsTrue() { // Use StringUtils containsIgnoreCase to avoid case insensitive issues Assert.assertTrue(StringUtils.containsIgnoreCase(src, dest)); } -} \ No newline at end of file +}