Repository: commons-lang Updated Branches: refs/heads/master ae865193e -> 849578d3a
LANG-1171 Add null safe compare methods in StringUtils : - StringUtils.compare(String str1, String str2); - StringUtils.compare(String str1, String str2, boolean nullIsLess); - StringUtils.compareIgnoreCase(String str1, String str2); - StringUtils.compareIgnoreCase(String str1, String str2, boolean nullIsLess); Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/94ec5a11 Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/94ec5a11 Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/94ec5a11 Branch: refs/heads/master Commit: 94ec5a11122b2e60fbffcc35373c978c839bf8ae Parents: 00fafe7 Author: Loic Guibert <lfdummy-apa...@yahoo.fr> Authored: Mon Oct 5 17:00:50 2015 +0400 Committer: Loic Guibert <lfdummy-apa...@yahoo.fr> Committed: Mon Oct 5 17:00:50 2015 +0400 ---------------------------------------------------------------------- .../org/apache/commons/lang3/StringUtils.java | 176 ++++++++++++++++++- .../lang3/StringUtilsEqualsIndexOfTest.java | 69 ++++++++ 2 files changed, 244 insertions(+), 1 deletion(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-lang/blob/94ec5a11/src/main/java/org/apache/commons/lang3/StringUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java index 3f0314f..cb39120 100644 --- a/src/main/java/org/apache/commons/lang3/StringUtils.java +++ b/src/main/java/org/apache/commons/lang3/StringUtils.java @@ -35,7 +35,7 @@ import java.util.regex.Pattern; * - checks if a String contains text</li> * <li><b>Trim/Strip</b> * - removes leading and trailing whitespace</li> - * <li><b>Equals</b> + * <li><b>Equals/Compare</b> * - compares two strings null-safe</li> * <li><b>startsWith</b> * - check if a String starts with a prefix null-safe</li> @@ -830,6 +830,180 @@ public class StringUtils { } } + // Compare + //----------------------------------------------------------------------- + /** + * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> + * <ul> + * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> + * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> + * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> + * </ul> + * + * <p>This is a {@code null} safe version of :</p> + * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> + * + * <p>{@code null} value is considered less than non-{@code null} value. + * Two {@code null} references are considered equal.</p> + * + * <pre> + * StringUtils.compare(null, null) = 0 + * StringUtils.compare(null , "a") < 0 + * StringUtils.compare("a", null) > 0 + * StringUtils.compare("abc", "abc") = 0 + * StringUtils.compare("a", "b") < 0 + * StringUtils.compare("b", "a") > 0 + * StringUtils.compare("a", "B") > 0 + * StringUtils.compare("ab", "abc") < 0 + * </pre> + * + * @see #compare(String, String, boolean) + * @see String#compareTo(String) + * @param str1 the String to compare from + * @param str2 the String to compare to + * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2} + */ + public static int compare(final String str1, final String str2) { + return compare(str1, str2, true); + } + + /** + * <p>Compare two Strings lexicographically, as per {@link String#compareTo(String)}, returning :</p> + * <ul> + * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> + * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> + * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> + * </ul> + * + * <p>This is a {@code null} safe version of :</p> + * <blockquote><pre>str1.compareTo(str2)</pre></blockquote> + * + * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. + * Two {@code null} references are considered equal.</p> + * + * <pre> + * StringUtils.compare(null, null, *) = 0 + * StringUtils.compare(null , "a", true) < 0 + * StringUtils.compare(null , "a", false) > 0 + * StringUtils.compare("a", null, true) > 0 + * StringUtils.compare("a", null, false) < 0 + * StringUtils.compare("abc", "abc", *) = 0 + * StringUtils.compare("a", "b", *) < 0 + * StringUtils.compare("b", "a", *) > 0 + * StringUtils.compare("a", "B", *) > 0 + * StringUtils.compare("ab", "abc", *) < 0 + * </pre> + * + * @see String#compareTo(String) + * @param str1 the String to compare from + * @param str2 the String to compare to + * @param nullIsLess whether consider {@code null} value less than non-{@code null} value + * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2} + */ + public static int compare(final String str1, final String str2, final boolean nullIsLess) { + if (str1 == str2) { + return 0; + } + if (str1 == null) { + return nullIsLess ? -1 : 1; + } + if (str2 == null) { + return nullIsLess ? 1 : - 1; + } + return str1.compareTo(str2); + } + + /** + * <p>Compare two Strings lexicographically, ignoring case differences, + * as per {@link String#compareToIgnoreCase(String)}, returning :</p> + * <ul> + * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> + * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> + * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> + * </ul> + * + * <p>This is a {@code null} safe version of :</p> + * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> + * + * <p>{@code null} value is considered less than non-{@code null} value. + * Two {@code null} references are considered equal. + * Comparison is case insensitive.</p> + * + * <pre> + * StringUtils.compareIgnoreCase(null, null) = 0 + * StringUtils.compareIgnoreCase(null , "a") < 0 + * StringUtils.compareIgnoreCase("a", null) > 0 + * StringUtils.compareIgnoreCase("abc", "abc") = 0 + * StringUtils.compareIgnoreCase("abc", "ABC") = 0 + * StringUtils.compareIgnoreCase("a", "b") < 0 + * StringUtils.compareIgnoreCase("b", "a") > 0 + * StringUtils.compareIgnoreCase("a", "B") < 0 + * StringUtils.compareIgnoreCase("A", "b") < 0 + * StringUtils.compareIgnoreCase("ab", "ABC") < 0 + * </pre> + * + * @see #compareIgnoreCase(String, String, boolean) + * @see String#compareToIgnoreCase(String) + * @param str1 the String to compare from + * @param str2 the String to compare to + * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, + * ignoring case differences. + */ + public static int compareIgnoreCase(final String str1, final String str2) { + return compareIgnoreCase(str1, str2, true); + } + + /** + * <p>Compare two Strings lexicographically, ignoring case differences, + * as per {@link String#compareToIgnoreCase(String)}, returning :</p> + * <ul> + * <li>{@code int = 0}, if {@code str1} is equal to {@code str2} (or both {@code null})</li> + * <li>{@code int < 0}, if {@code str1} is less than {@code str2}</li> + * <li>{@code int > 0}, if {@code str1} is greater than {@code str2}</li> + * </ul> + * + * <p>This is a {@code null} safe version of :</p> + * <blockquote><pre>str1.compareToIgnoreCase(str2)</pre></blockquote> + * + * <p>{@code null} inputs are handled according to the {@code nullIsLess} parameter. + * Two {@code null} references are considered equal. + * Comparison is case insensitive.</p> + * + * <pre> + * StringUtils.compareIgnoreCase(null, null, *) = 0 + * StringUtils.compareIgnoreCase(null , "a", true) < 0 + * StringUtils.compareIgnoreCase(null , "a", false) > 0 + * StringUtils.compareIgnoreCase("a", null, true) > 0 + * StringUtils.compareIgnoreCase("a", null, false) < 0 + * StringUtils.compareIgnoreCase("abc", "abc", *) = 0 + * StringUtils.compareIgnoreCase("abc", "ABC", *) = 0 + * StringUtils.compareIgnoreCase("a", "b", *) < 0 + * StringUtils.compareIgnoreCase("b", "a", *) > 0 + * StringUtils.compareIgnoreCase("a", "B", *) < 0 + * StringUtils.compareIgnoreCase("A", "b", *) < 0 + * StringUtils.compareIgnoreCase("ab", "abc", *) < 0 + * </pre> + * + * @see String#compareToIgnoreCase(String) + * @param str1 the String to compare from + * @param str2 the String to compare to + * @param nullIsLess whether consider {@code null} value less than non-{@code null} value + * @return < 0, 0, > 0, if {@code str1} is respectively less, equal ou greater than {@code str2}, + * ignoring case differences. + */ + public static int compareIgnoreCase(final String str1, final String str2, final boolean nullIsLess) { + if (str1 == str2) { + return 0; + } + if (str1 == null) { + return nullIsLess ? -1 : 1; + } + if (str2 == null) { + return nullIsLess ? 1 : - 1; + } + return str1.compareToIgnoreCase(str2); + } + // IndexOf //----------------------------------------------------------------------- /** http://git-wip-us.apache.org/repos/asf/commons-lang/blob/94ec5a11/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java index d2b6418..b45a5f6 100644 --- a/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java +++ b/src/test/java/org/apache/commons/lang3/StringUtilsEqualsIndexOfTest.java @@ -578,6 +578,75 @@ public class StringUtilsEqualsIndexOfTest { //----------------------------------------------------------------------- @Test + public void testCompare_StringString() { + assertTrue(StringUtils.compare(null, null) == 0); + assertTrue(StringUtils.compare(null, "a") < 0); + assertTrue(StringUtils.compare("a", null) > 0); + assertTrue(StringUtils.compare("abc", "abc") == 0); + assertTrue(StringUtils.compare("a", "b") < 0); + assertTrue(StringUtils.compare("b", "a") > 0); + assertTrue(StringUtils.compare("a", "B") > 0); + assertTrue(StringUtils.compare("abc", "abd") < 0); + assertTrue(StringUtils.compare("ab", "abc") < 0); + assertTrue(StringUtils.compare("ab", "ab ") < 0); + assertTrue(StringUtils.compare("abc", "ab ") > 0); + } + + @Test + public void testCompare_StringStringBoolean() { + assertTrue(StringUtils.compare(null, null, false) == 0); + assertTrue(StringUtils.compare(null, "a", true) < 0); + assertTrue(StringUtils.compare(null, "a", false) > 0); + assertTrue(StringUtils.compare("a", null, true) > 0); + assertTrue(StringUtils.compare("a", null, false) < 0); + assertTrue(StringUtils.compare("abc", "abc", false) == 0); + assertTrue(StringUtils.compare("a", "b", false) < 0); + assertTrue(StringUtils.compare("b", "a", false) > 0); + assertTrue(StringUtils.compare("a", "B", false) > 0); + assertTrue(StringUtils.compare("abc", "abd", false) < 0); + assertTrue(StringUtils.compare("ab", "abc", false) < 0); + assertTrue(StringUtils.compare("ab", "ab ", false) < 0); + assertTrue(StringUtils.compare("abc", "ab ", false) > 0); + } + + @Test + public void testCompareIgnoreCase_StringString() { + assertTrue(StringUtils.compareIgnoreCase(null, null) == 0); + assertTrue(StringUtils.compareIgnoreCase(null, "a") < 0); + assertTrue(StringUtils.compareIgnoreCase("a", null) > 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "abc") == 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "ABC") == 0); + assertTrue(StringUtils.compareIgnoreCase("a", "b") < 0); + assertTrue(StringUtils.compareIgnoreCase("b", "a") > 0); + assertTrue(StringUtils.compareIgnoreCase("a", "B") < 0); + assertTrue(StringUtils.compareIgnoreCase("A", "b") < 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "ABD") < 0); + assertTrue(StringUtils.compareIgnoreCase("ab", "ABC") < 0); + assertTrue(StringUtils.compareIgnoreCase("ab", "AB ") < 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "AB ") > 0); + } + + @Test + public void testCompareIgnoreCase_StringStringBoolean() { + assertTrue(StringUtils.compareIgnoreCase(null, null, false) == 0); + assertTrue(StringUtils.compareIgnoreCase(null, "a", true) < 0); + assertTrue(StringUtils.compareIgnoreCase(null, "a", false) > 0); + assertTrue(StringUtils.compareIgnoreCase("a", null, true) > 0); + assertTrue(StringUtils.compareIgnoreCase("a", null, false) < 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "abc", false) == 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "ABC", false) == 0); + assertTrue(StringUtils.compareIgnoreCase("a", "b", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("b", "a", false) > 0); + assertTrue(StringUtils.compareIgnoreCase("a", "B", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("A", "b", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "ABD", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("ab", "ABC", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("ab", "AB ", false) < 0); + assertTrue(StringUtils.compareIgnoreCase("abc", "AB ", false) > 0); + } + + //----------------------------------------------------------------------- + @Test public void testIndexOf_char() { assertEquals(-1, StringUtils.indexOf(null, ' ')); assertEquals(-1, StringUtils.indexOf("", ' '));