Java 使用流生成短[]
在此基础上,我尝试生成一系列原始短裤。事实证明,这比预期的要困难得多Java 使用流生成短[],java,java-8,java-stream,Java,Java 8,Java Stream,在此基础上,我尝试生成一系列原始短裤。事实证明,这比预期的要困难得多 Short[]range=IntStream.range(0500).mapToObj(value->(Short)value).toArray(Short[]::new)工作正常,但: short[]range=IntStream.range(0500).mapToObj(value->(short)value).toArray(short[]::new)生成了一个编译器错误: method toArray in inter
Short[]range=IntStream.range(0500).mapToObj(value->(Short)value).toArray(Short[]::new)
工作正常,但:
short[]range=IntStream.range(0500).mapToObj(value->(short)value).toArray(short[]::new)
生成了一个编译器错误:
method toArray in interface Stream<T> cannot be applied to given types;
required: IntFunction<A[]>
found: short[]::new
reason: inference variable A has incompatible bounds
equality constraints: short
upper bounds: Object
where A,T are type-variables:
A extends Object declared in method <A>toArray(IntFunction<A[]>)
T extends Object declared in interface Stream
接口流中的toArray方法不能应用于给定类型;
必需:IntFunction
找到:short[]::new
原因:推理变量A的边界不兼容
平等约束:简短
上限:对象
其中A,T是类型变量:
在方法toArray(IntFunction)中声明的扩展对象
T扩展接口流中声明的对象
这似乎是两个问题的交叉:
short
s的实现int
数字流。调用ToSortArray()
时,它们会使用(short)
强制转换操作自动转换为short
类型,因此可能发生溢出。所以要小心使用
还有
intstreamx.toByteArray()
,intstreamx.tocharray()
,和doublestreamx.toFloatArray()
,规范的方法是实现自定义收集器
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);
}
}
缺点是Collector
s仅适用于引用类型(因为泛型不支持基元类型),因此您必须求助于boxed()
,并且收集器不能利用有关元素数量的信息(如果有的话)。因此,性能可能比原始数据流上的toArray()
差得多
因此,追求更高性能的解决方案(我将此限制在单线程情况下)将如下所示:
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();
}
使用short而不是int会使您的生活变得复杂。这不会带来任何性能或内存优势,但会使代码更难编写。我已经多年没有在任何API中使用short或看到short了。@JBNizet我明白了,但该字段对应于类型为short
(由于遗留原因,我无法更改数据库架构)的数据库列。通过提前存储short
,在将数据发送到数据库之前,我可以防止在最后一分钟出现铸造错误的可能性。您正确理解了问题。streams库设计者认为不值得添加ShortStream等,取消装箱不能与泛型互操作,添加特殊的ToSortArray()
方法也不起作用,因为您可以在流上调用它们,我只是简单地使用for循环,而不是尝试使用streams。由于性能原因,JVM可能是32位或64位边界的内存对齐短路。请参阅和的反论点。重点是:我们不知道引擎盖下发生了什么。如果我是你,我会找到一种方法来测量你的特定设置(硬件/软件)的实际内存使用情况,如果它起到了作用,那就千方百计去做。
short[] array=IntStream.range(0, 500).boxed().collect(ShortCollector.TO_ARRAY);
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();
}
short[] array=toShortArray(IntStream.range(0, 500));