[PATCH] enhancement proposal for String concatenation

Remi Forax forax at univ-mlv.fr
Sat Mar 9 09:57:34 UTC 2019


yes,
but unlike Strig.format() where the number of objects to concatenate is usually known, with String.join() you can only detect if the delimiter is constant, you don't know how many strings you have to concatenate, so the best you can do is a kind of loop customization, given that JITs also do this optimization, it's not obvious that perf can be better.

Rémi

----- Mail original -----
> De: "Roger Riggs" <roger.riggs at oracle.com>
> À: "core-libs-dev" <core-libs-dev at openjdk.java.net>
> Envoyé: Samedi 9 Mars 2019 08:52:41
> Objet: Re: [PATCH] enhancement proposal for String concatenation

> Hi,
> 
> Copy/paste is almost always brings more of a liability than an asset
> due to long term maintenance, skew, etc.
> 
> Another possibility for StringJoiner is to look at the approach being
> investigated
> for String.format in JEP 348[1].
> 
> It leverages the work already done to support String concatenation ("+")
> in JEP 280[2].
> 
> [1] https://openjdk.java.net/jeps/348
> [2] https://openjdk.java.net/jeps/280
> 
> Regards, Roger
> 
> On 3/8/19 8:00 PM, Ivan Gerasimov wrote:
>> Hi Sergei!
>>
>> As you said, this new class is pretty much like StringJoiner with
>> reduced functionality.
>>
>> For appending all elements of an Iterable you could use list.forEach(s
>> -> sj.add(s)).
>>
>> With kind regards,
>> Ivan
>>
>> On 3/8/19 11:22 AM, Сергей Цыпанов wrote:
>>> Hello,
>>>
>>> I have an enhancement proposal for some cases of String concatenation
>>> in Java.
>>>
>>> Currently we concat Strings mostly using java.lang.StringBuilder. The
>>> main disadvantage of StringBuilder is underlying char array or rather
>>> a need to resize it when the capacity is about to exceed array length
>>> and subsequent copying of array content into newly allocated array.
>>>
>>> One alternative solution existing is StringJoiner. Before JDK 9 it
>>> was a kind of decorator over StringBuilder, but later it was reworked
>>> in order to store appended Strings into String[] and overall capacity
>>> accumulated into int field. This makes it possible to allocate char[]
>>> only once and of exact size in toString() method reducing allocation
>>> cost.
>>>
>>> My proposal is to copy-paste the code of StringJoinder into newly
>>> created class java.util.StringChain, drop the code responsible for
>>> delimiter, prefix and suffix and use it instead of StringBuilder in
>>> common StringBuilder::append concatenation pattern.
>>>
>>> Possible use-cases for proposed code are:
>>> - plain String concatenation
>>> - String::chain (new methods)
>>> - Stream.collect(Collectors.joining())
>>> - StringConcatFactory
>>>
>>> We can create new methods String.chain(Iterable<CharSequence>) and
>>> String.chain(CharSequence...) which allow to encapsulate boilerplate
>>> code like
>>>
>>>
>>>    StringBuilder sb = new StringBuilder();
>>>    for (CharSequence cs : charSequences) {
>>>      sb.append(cs);
>>>    }
>>>    String result = sb.toString():
>>>
>>>
>>> into one line:
>>>
>>>
>>>    String result = String.chain(charSequences);
>>>
>>>
>>>
>>> As of performance I've done some measurements using JMH on my work
>>> machine (Intel i7-7700) for both Latin and non-Latin Strings of
>>> different size and count.
>>> Here are the results:
>>>
>>> https://github.com/stsypanov/string-chain/blob/master/results/StringBuilderVsStringChainBenchmark.txt
>>>
>>>
>>> There is a few corner cases (e.g. 1000 Strings of length 1 appended)
>>> when StringBuilder takes over StringChain constructed with default
>>> capacity of 8, but StringChain constructed with exact added Strings
>>> count almost always wins, especially when dealing with non-Latin
>>> chars (Russian in my case).
>>>
>>> I've also created a separate repo on GitHub with benchmarks:
>>>
>>> https://github.com/stsypanov/string-chain
>>>
>>> Key feature here is ability to allocate String array of exact size is
>>> cases we know added elements count.
>>> Thus I think that if the change will be accepted we can add also an
>>> overloaded method String.chain(Collection<CharSequence>) as
>>> Collection::size allows to contruct StringChain of exact size.
>>>
>>> Patch is attached.
>>>
>>> Kind regards,
>>> Sergei Tsypanov


More information about the core-libs-dev mailing list