I know that the Java Stream<>
interface provides several ways to convert a stream to an array. But the Collection.toArray(T[] array)
method is a little different. It has a few clever (at the time) requirements, including:
- If the array you pass is big enough, the array you pass must be used; otherwise a new one must be created.
- If the array is bigger than necessary,
null
must be added after the last element.
So if my Collection<T>
implementation retrieves its values from some Stream<FooBar>
(with a converter strategy that converts to T
, how can I convert from my stream to the array required by Collection.toArray(T[] array)
?
Without a lot of thought, it would seem I have to do this:
@Override
public <T> T[] toArray(T[] array) {
try (final Stream<FooBar> stream = getStream()) {
T[] result = stream.map(converter::toT).toArray(length ->
(T[])Array.newInstance(array.getClass(), length));
if(result.length <= array.length) {
System.arraycopy(result, 0, array, 0, result.length);
if(result.length < array.length) {
array[result.length] = null;
}
result = array;
}
}
return result;
}
But is there some more concise way to do this? Is there some way I could transfer the stream directly into the given array if possible? And does the Stream<>
API already provide for something like this: creating an array as the Collection<>.toArray(T[] array)
API expects?
Response to possible duplicates
I know how to convert a stream to an array. This question is very specific: how to follow the contract of Collection.toArray(T[] array)
. I don't think this is a duplicate, for two reasons: the other answers do not re-use an existing array if it is big enough, and they don't mark an element with null
if the existing array is too big.