The canonical method will implement a custom Collector .
class ShortCollector { public static Collector<Integer,ShortCollector,short[]> TO_ARRAY =Collector.of(ShortCollector::new, ShortCollector::add, ShortCollector::merge, c->c.get()); short[] array=new short[100]; int pos; public void add(int value) { int ix=pos; if(ix==array.length) array=Arrays.copyOf(array, ix*2); array[ix]=(short)value; pos=ix+1; } public ShortCollector merge(ShortCollector c) { int ix=pos, cIx=c.pos, newSize=ix+cIx; if(array.length<newSize) array=Arrays.copyOf(array, newSize); System.arraycopy(c.array, 0, array, ix, cIx); return this; } public short[] get() { return pos==array.length? array: Arrays.copyOf(array, pos); } }
Then you can use it as
short[] array=IntStream.range(0, 500).boxed().collect(ShortCollector.TO_ARRAY);
The disadvantage is that Collector works only for reference types (since Generics does not support primitive types), so you need to resort to boxed() , and collectors cannot use information about the number of elements (if they are ever available). Thus, performance will be much worse than toArray() in a primitive data stream.
So, a solution aimed at increasing productivity (I limit this for a single-threaded case) will look like this:
public static short[] toShortArray(IntStream is) { Spliterator.OfInt sp = is.spliterator(); long l=sp.getExactSizeIfKnown(); if(l>=0) { if(l>Integer.MAX_VALUE) throw new OutOfMemoryError(); short[] array=new short[(int)l]; sp.forEachRemaining(new IntConsumer() { int ix; public void accept(int value) { array[ix++]=(short)value; } }); return array; } final class ShortCollector implements IntConsumer { int bufIx, currIx, total; short[][] buffer=new short[25][]; short[] current=buffer[0]=new short[64]; public void accept(int value) { int ix = currIx; if(ix==current.length) { current=buffer[++bufIx]=new short[ix*2]; total+=ix; ix=0; } current[ix]=(short)value; currIx=ix+1; } short[] toArray() { if(bufIx==0) return currIx==current.length? current: Arrays.copyOf(current, currIx); int p=0; short[][] buf=buffer; short[] result=new short[total+currIx]; for(int bIx=0, e=bufIx, l=buf[0].length; bIx<e; bIx++, p+=l, l+=l) System.arraycopy(buf[bIx], 0, result, p, l); System.arraycopy(current, 0, result, p, currIx); return result; } } ShortCollector c=new ShortCollector(); sp.forEachRemaining(c); return c.toArray(); }
You can use it as
short[] array=toShortArray(IntStream.range(0, 500));