RFR: 8305774: String.join(CharSequence, Iterable) can be optimized if Iterable is a Collection [v2]
Chen Liang
liach at openjdk.org
Mon Apr 10 03:39:49 UTC 2023
On Sun, 9 Apr 2023 02:28:37 GMT, Tingjun Yuan <duke at openjdk.org> wrote:
>> In the current implementation of `String.join(CharSequence, Iterable)`, the temp array `elems` is always initialized with a length of 8. It will cause many array recreations when the `Iterable` contains more than 8 elements. Furthermore, it's very common that an `Iterable` is also a `Collection`. So if the `Iterable` is an instance of `Collection`, the initial length of the array can be `((Collection<?>)elements).size()`. It will not change the current behavior even if the `Collection` is modified asynchronously.
>>
>> I don't know whether this change requires a CSR request.
>
> Tingjun Yuan has updated the pull request incrementally with one additional commit since the last revision:
>
> Add benchmark
Nah. I mean like:
public static String join(CharSequence delimiter,
Iterable<? extends CharSequence> elements) {
Objects.requireNonNull(delimiter);
Objects.requireNonNull(elements);
var delim = delimiter.toString();
Object[] elems;
final int size;
if (elements instanceof Collection<?> c) {
elems = c.toArray();
size = elems.length;
for (int i = 0; i < size; i++) {
elems[i] = String.valueOf(elems[i]);
}
} else {
elems = new String[elements instanceof Collection<?> c ? c.size() : 8]; // or whatever spliterator you decide to use
size = 0;
for (CharSequence cs: elements) {
if (size >= elems.length) {
elems = Arrays.copyOf(elems, elems.length << 1);
}
elems[size++] = String.valueOf(cs);
}
}
return join("", "", delim, elems, size);
}
// ...
static String join(String prefix, String suffix, String delimiter, Object[] elements, int size) { // change array type to Object[], cast on access elements
-------------
PR Comment: https://git.openjdk.org/jdk/pull/13383#issuecomment-1501351704
More information about the core-libs-dev
mailing list