Der kanonische Weg wäre die Implementierung einer benutzerdefinierten 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);
}
}
Dann könnten Sie es verwenden, wie
short[] array=IntStream.range(0, 500).boxed().collect(ShortCollector.TO_ARRAY);
Der Nachteil ist, dass Collector
s nur für Referenztypen arbeiten (wie Generics nicht primitive Typen nicht unterstützt), so dass Sie boxed()
zurückgreifen und Sammler können keine Informationen über die Anzahl der Elemente verwenden (falls überhaupt verfügbar). Somit ist die Leistung wahrscheinlich viel schlechter als toArray()
auf einem primitiven Datenstrom.
So wurde eine Lösung für eine höhere Leistung Streben (I begrenzen dies auf die einzelnen Gewinde Fall) wird wie folgt aussehen:
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();
}
Sie es wie
short[] array=toShortArray(IntStream.range(0, 500));
verwenden
Sie machen Ihre eigenes Leben kompliziert durch Verwendung von kurzen statt int. Das bringt keinen Performance- oder Speichervorteil, macht aber Ihren Code schwieriger zu schreiben. Ich habe seit Jahren kein kurzes oder kurzes API verwendet. –
@ JBNizet Ich bekomme das, aber das Feld entspricht einer Datenbankspalte vom Typ 'short' (ich kann das Datenbankschema aus Legacy-Gründen nicht ändern). Durch die Speicherung von 'short' vorne verhindere ich in letzter Minute die Möglichkeit eines Wurffehlers, bevor ich die Daten an die Datenbank sende. – Gili
Sie verstehen das Problem richtig.Die Designer der Streams-Bibliothek entschieden, dass es nicht wert war, ShortStream usw. hinzuzufügen, das Unboxing interoperierte nicht mit Generics, und das Hinzufügen spezieller 'toShortArray()' -Methoden würde auch nicht funktionieren, weil man sie zB mit einem 'Stream' aufrufen könnte. –