使用流生成short

在使用连续的短裤范围填充列表的基础上,我尝试生成一组原始短裤。 事实certificate这比预期的要难得多。

Short[] range = IntStream.range(0, 500).mapToObj(value -> (short) value).toArray(Short[]::new)工作但是:

short[] range = IntStream.range(0, 500).mapToObj(value -> (short) value).toArray(short[]::new)生成编译错误:

 method toArray in interface Stream cannot be applied to given types; required: IntFunction 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 toArray(IntFunction) T extends Object declared in interface Stream 

这似乎是两个问题的交集:

  1. 原始Stream API不提供short s的实现。
  2. 非原始Stream API似乎不提供返回基本数组的机制。

有任何想法吗?

您可以考虑使用我的StreamEx库。 它使用其他方法扩展了标准和流。 我的库的目标之一是更好地与旧代码互操作。 特别是它有IntStreamEx.toShortArray()IntStreamEx.of(short...)

 short[] numbers = IntStreamEx.range(500).toShortArray(); short[] evenNumbers = IntStreamEx.of(numbers).map(x -> x*2).toShortArray(); 

请注意,它仍然是int数字流。 当调用toShortArray() ,它们会使用(short) toShortArray()转换操作自动转换为short类型,因此可以溢出。 所以要小心使用。

还有IntStreamEx.toByteArray()IntStreamEx.toCharArray()DoubleStreamEx.toFloatArray()

规范的方法是实现自定义Collector

 class ShortCollector { public static Collector 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 

然后你可以像使用它一样

 short[] array=IntStream.range(0, 500).boxed().collect(ShortCollector.TO_ARRAY); 

缺点是Collector仅适用于引用类型(因为Generics不支持基本类型),因此您必须求助于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 

你可以像使用它一样

 short[] array=toShortArray(IntStream.range(0, 500));