Strings.removeAllFromStart/End only call substring() once. Java 7 update 6 changed the cost of String.substring from O(1) to O(n). This commit changes the two removeAll methods to make one substring calls rather than one per match.
Project: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/commit/28f7c594 Tree: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/tree/28f7c594 Diff: http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/diff/28f7c594 Branch: refs/heads/master Commit: 28f7c5942fb15e890da1e585d085af81336b0e5c Parents: 4e78e67 Author: Sam Corbett <[email protected]> Authored: Tue May 12 20:26:57 2015 +0100 Committer: Sam Corbett <[email protected]> Committed: Thu May 14 11:05:31 2015 +0100 ---------------------------------------------------------------------- .../main/java/brooklyn/util/text/Strings.java | 30 +++++++++++++------- .../java/brooklyn/util/text/StringsTest.java | 6 ++++ 2 files changed, 25 insertions(+), 11 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/28f7c594/utils/common/src/main/java/brooklyn/util/text/Strings.java ---------------------------------------------------------------------- diff --git a/utils/common/src/main/java/brooklyn/util/text/Strings.java b/utils/common/src/main/java/brooklyn/util/text/Strings.java index 5736441..05957c4 100644 --- a/utils/common/src/main/java/brooklyn/util/text/Strings.java +++ b/utils/common/src/main/java/brooklyn/util/text/Strings.java @@ -151,20 +151,24 @@ public class Strings { return string; } - /** as removeFromEnd, but repeats until all such suffixes are gone */ - public static String removeAllFromEnd(String string, String ...suffixes) { + /** + * As removeFromEnd, but repeats until all such suffixes are gone + */ + public static String removeAllFromEnd(String string, String... suffixes) { + if (isEmpty(string)) return string; + int index = string.length(); boolean anotherLoopNeeded = true; while (anotherLoopNeeded) { if (isEmpty(string)) return string; anotherLoopNeeded = false; for (String suffix : suffixes) - if (string.endsWith(suffix)) { - string = string.substring(0, string.length() - suffix.length()); + if (!isEmpty(suffix) && string.startsWith(suffix, index - suffix.length())) { + index -= suffix.length(); anotherLoopNeeded = true; break; } } - return string; + return string.substring(0, index); } /** @@ -193,20 +197,24 @@ public class Strings { return string; } - /** as removeFromStart, but repeats until all such suffixes are gone */ - public static String removeAllFromStart(String string, String ...prefixes) { + /** + * As {@link #removeFromStart(String, String)}, repeating until all such prefixes are gone. + */ + public static String removeAllFromStart(String string, String... prefixes) { + int index = 0; boolean anotherLoopNeeded = true; while (anotherLoopNeeded) { if (isEmpty(string)) return string; anotherLoopNeeded = false; - for (String prefix : prefixes) - if (string.startsWith(prefix)) { - string = string.substring(prefix.length()); + for (String prefix : prefixes) { + if (!isEmpty(prefix) && string.startsWith(prefix, index)) { + index += prefix.length(); anotherLoopNeeded = true; break; } + } } - return string; + return string.substring(index); } /** convenience for {@link com.google.common.base.Joiner} */ http://git-wip-us.apache.org/repos/asf/incubator-brooklyn/blob/28f7c594/utils/common/src/test/java/brooklyn/util/text/StringsTest.java ---------------------------------------------------------------------- diff --git a/utils/common/src/test/java/brooklyn/util/text/StringsTest.java b/utils/common/src/test/java/brooklyn/util/text/StringsTest.java index a9780c1..5759c6f 100644 --- a/utils/common/src/test/java/brooklyn/util/text/StringsTest.java +++ b/utils/common/src/test/java/brooklyn/util/text/StringsTest.java @@ -108,12 +108,15 @@ public class StringsTest extends FixedLocaleTest { public void testRemoveAllFromEnd() { assertEquals(Strings.removeAllFromEnd("", "bar"), ""); assertEquals(Strings.removeAllFromEnd(null, "bar"), null); + assertEquals(Strings.removeAllFromEnd("foo", ""), "foo"); assertEquals(Strings.removeAllFromEnd("foobar", "foo", "bar"), ""); assertEquals(Strings.removeAllFromEnd("foobar", "ar", "car", "b", "o"), "f"); // test they are applied in order assertEquals(Strings.removeAllFromEnd("foobar", "ar", "car", "b", "ob"), "foo"); assertEquals(Strings.removeAllFromEnd("foobar", "zz", "x"), "foobar"); + assertEquals(Strings.removeAllFromEnd("foobarbaz", "bar", "baz"), "foo"); + assertEquals(Strings.removeAllFromEnd("foobarbaz", "baz", "", "foo", "bar", "baz"), ""); } public void testRemoveFromStart() { @@ -129,6 +132,7 @@ public class StringsTest extends FixedLocaleTest { public void testRemoveAllFromStart() { assertEquals(Strings.removeAllFromStart("", "foo"), ""); assertEquals(Strings.removeAllFromStart(null, "foo"), null); + assertEquals(Strings.removeAllFromStart("foo", ""), "foo"); assertEquals(Strings.removeAllFromStart("foobar", "foo"), "bar"); assertEquals(Strings.removeAllFromStart("foo", "bar"), "foo"); @@ -138,6 +142,8 @@ public class StringsTest extends FixedLocaleTest { assertEquals(Strings.removeAllFromStart("foobar", "ob", "fo", "o"), "ar"); // test they are applied in order, "ob" doesn't match because "o" eats the o assertEquals(Strings.removeAllFromStart("foobar", "o", "fo", "ob"), "bar"); + assertEquals(Strings.removeAllFromStart("foobarbaz", "bar", "foo"), "baz"); + assertEquals(Strings.removeAllFromStart("foobarbaz", "baz", "bar", "foo"), ""); } public void testRemoveFromStart2() {
