Skip to content

Commit 31a1989

Browse files
committed
performance refine for StringUtils.center
1 parent e233ab6 commit 31a1989

File tree

2 files changed

+159
-3
lines changed

2 files changed

+159
-3
lines changed

src/main/java/org/apache/commons/lang3/StringUtils.java

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -621,9 +621,11 @@ public static String center(String str, final int size, final char padChar) {
621621
if (pads <= 0) {
622622
return str;
623623
}
624-
str = leftPad(str, strLen + pads / 2, padChar);
625-
str = rightPad(str, size, padChar);
626-
return str;
624+
StringBuilder stringBuilder = new StringBuilder(size);
625+
repeat(stringBuilder, padChar, pads / 2);
626+
stringBuilder.append(str);
627+
repeat(stringBuilder, padChar, size - (strLen + pads / 2));
628+
return stringBuilder.toString();
627629
}
628630

629631
/**
@@ -6253,6 +6255,23 @@ public static String repeat(final char ch, final int repeat) {
62536255
return new String(buf);
62546256
}
62556257

6258+
/**
6259+
* <p>Make the padding using the specified delimiter repeated
6260+
* to a given length, and fill the result to a StringBuilder</p>
6261+
*
6262+
* This function works like {@code stringBuilder.append(repeat(ch,repeat))}, but runs faster.
6263+
*
6264+
* @param stringBuilder stringBuilder to fill
6265+
* @param ch character to repeat
6266+
* @param repeat number of times to repeat char, negative treated as zero
6267+
* @see #repeat(char, int)
6268+
*/
6269+
static void repeat(StringBuilder stringBuilder, final char ch, final int repeat) {
6270+
for (int i = repeat - 1; i >= 0; i--) {
6271+
stringBuilder.append(ch);
6272+
}
6273+
}
6274+
62566275
/**
62576276
* <p>Repeat a String {@code repeat} times to form a
62586277
* new String.</p>
Lines changed: 137 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,137 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.commons.lang3;
18+
19+
import org.openjdk.jmh.annotations.Benchmark;
20+
import org.openjdk.jmh.annotations.BenchmarkMode;
21+
import org.openjdk.jmh.annotations.Mode;
22+
import org.openjdk.jmh.annotations.OutputTimeUnit;
23+
import org.openjdk.jmh.annotations.Scope;
24+
import org.openjdk.jmh.annotations.State;
25+
26+
import java.util.concurrent.TimeUnit;
27+
28+
import static org.apache.commons.lang3.StringUtils.leftPad;
29+
import static org.apache.commons.lang3.StringUtils.repeat;
30+
import static org.apache.commons.lang3.StringUtils.rightPad;
31+
32+
/**
33+
* Test to show whether using BitSet for removeAll() methods is faster than using HashSet.
34+
*/
35+
@BenchmarkMode(Mode.AverageTime)
36+
@OutputTimeUnit(TimeUnit.NANOSECONDS)
37+
@State(Scope.Thread)
38+
public class StringUtilCenterTest {
39+
40+
@Benchmark
41+
public void test0Old() {
42+
centerOld("a", 20, 'a');
43+
}
44+
45+
@Benchmark
46+
public void test0New() {
47+
centerNew("a", 20, 'a');
48+
}
49+
50+
@Benchmark
51+
public void test1Old() {
52+
centerOld("a", 10000000, ' ');
53+
}
54+
55+
@Benchmark
56+
public void test1New() {
57+
centerNew("a", 10000000, ' ');
58+
}
59+
60+
/**
61+
* <p>Centers a String in a larger String of size {@code size}.
62+
* Uses a supplied character as the value to pad the String with.</p>
63+
*
64+
* <p>If the size is less than the String length, the String is returned.
65+
* A {@code null} String returns {@code null}.
66+
* A negative size is treated as zero.</p>
67+
*
68+
* <pre>
69+
* StringUtils.center(null, *, *) = null
70+
* StringUtils.center("", 4, ' ') = " "
71+
* StringUtils.center("ab", -1, ' ') = "ab"
72+
* StringUtils.center("ab", 4, ' ') = " ab "
73+
* StringUtils.center("abcd", 2, ' ') = "abcd"
74+
* StringUtils.center("a", 4, ' ') = " a "
75+
* StringUtils.center("a", 4, 'y') = "yayy"
76+
* </pre>
77+
*
78+
* @param str the String to center, may be null
79+
* @param size the int size of new String, negative treated as zero
80+
* @param padChar the character to pad the new String with
81+
* @return centered String, {@code null} if null String input
82+
* @since 2.0
83+
*/
84+
public static String centerNew(String str, final int size, final char padChar) {
85+
if (str == null || size <= 0) {
86+
return str;
87+
}
88+
final int strLen = str.length();
89+
final int pads = size - strLen;
90+
if (pads <= 0) {
91+
return str;
92+
}
93+
StringBuilder stringBuilder = new StringBuilder(size);
94+
repeat(stringBuilder, padChar, pads / 2);
95+
stringBuilder.append(str);
96+
repeat(stringBuilder, padChar, size - (strLen + pads / 2));
97+
return stringBuilder.toString();
98+
}
99+
100+
/**
101+
* <p>Centers a String in a larger String of size {@code size}.
102+
* Uses a supplied character as the value to pad the String with.</p>
103+
*
104+
* <p>If the size is less than the String length, the String is returned.
105+
* A {@code null} String returns {@code null}.
106+
* A negative size is treated as zero.</p>
107+
*
108+
* <pre>
109+
* StringUtils.center(null, *, *) = null
110+
* StringUtils.center("", 4, ' ') = " "
111+
* StringUtils.center("ab", -1, ' ') = "ab"
112+
* StringUtils.center("ab", 4, ' ') = " ab "
113+
* StringUtils.center("abcd", 2, ' ') = "abcd"
114+
* StringUtils.center("a", 4, ' ') = " a "
115+
* StringUtils.center("a", 4, 'y') = "yayy"
116+
* </pre>
117+
*
118+
* @param str the String to center, may be null
119+
* @param size the int size of new String, negative treated as zero
120+
* @param padChar the character to pad the new String with
121+
* @return centered String, {@code null} if null String input
122+
* @since 2.0
123+
*/
124+
public static String centerOld(String str, final int size, final char padChar) {
125+
if (str == null || size <= 0) {
126+
return str;
127+
}
128+
final int strLen = str.length();
129+
final int pads = size - strLen;
130+
if (pads <= 0) {
131+
return str;
132+
}
133+
str = leftPad(str, strLen + pads / 2, padChar);
134+
str = rightPad(str, size, padChar);
135+
return str;
136+
}
137+
}

0 commit comments

Comments
 (0)