StringBuilder and StringBuffer: add a new constructor with initial string AND initial capacity. Restrict passing a null into constructors
Sergey Ponomarev
stokito at gmail.com
Fri Oct 5 14:59:12 UTC 2018
Hi,
Both StringBuilder and StringBuffer have two constructors:
1. StringBuilder(int capacity) - Constructs a string builder with no
characters in it and an initial capacity specified by the capacity argument.
2. StringBuilder(String str) - Constructs a string builder initialized to
the contents of the specified string. The initial capacity of the string
builder is 16 plus the length of the string argument. It's code is:
public StringBuilder(String str) {
super(str.length() + 16); // call to StringBuilder(int capacity)
append(str);
}
I would like to propose to add the third constructor which combines the
first two:
3. StringBuilder(String seq, int capacity) - Constructs a string builder
initialized to the contents of the specified string with the initial
capacity specified by the capacity argument. Its code may look like:
public StringBuilder(CharSequence seq, int capacity) {
this(capacity);
append(initialString);
}
JUSTIFICATION
First of all the same constructor StringBuilder(String, Int32)
<https://docs.microsoft.com/en-us/dotnet/api/system.text.stringbuilder.-ctor?view=netframework-4.7.2#System_Text_StringBuilder__ctor_System_String_System_Int32_>
already
exists and is used in .NET/C#.
I analyzed my company's projects and the second constructor is popular
among developers and typically used for constructing big SQL queries:
StringBuilder query = new StringBuilder("SELECT * FROM users");
// a lot of conditional appends of search criteria
The problem is that typical queries are mostly big with length in range
200-600 chars while the string builder created by this constructor will
have a much smaller capacity.
So to avoid reallocations it's better to initialize the StringBuilder with
expected capacity but then we have to use the first constructor and
separate call of append():
StringBuilder query = new StringBuilder(512).append("SELECT * FROM
users");
And here is two problems:
1. Most developers are quite lazy or just don't think about this and will
prefer to use StringBuilder(String str) without specifying of initial
capacity. But if IDE's autocomplete suggest them already existed
constructor StringBuilder(String, int) they will probably use it instead.
2. Additional call of append() takes more place and is not so effective for
a performance because it has to ensure capacity while having a separate
constructor for this case can be optimized in future.
Another one issue is that while it said in StringBuilder javadoc that some
constructors may accept null string while in fact all constructor will
throw NPE on a null value. I think it's better to specify it explicitly in
JavaDoc.
Please see my patch against JDK master branch with the changes:
https://github.com/stokito/jdk/commit/2f5827b3001f5bd4e7b2f5eebc124a975e2a3e1c
(you can add ".patch" to the URL to get the raw patch file)
Regards,
Sergey Ponomarev
More information about the core-libs-dev
mailing list