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扩展接口流中声明的对象 这似乎是两个问题的交叉:

  • 原始流API不提供
    short
    s的实现
  • 非原语流API似乎没有提供返回原语数组的机制
  • 有什么想法吗?< / P >你可以考虑使用我的图书馆。它通过附加方法扩展了standand streams。我的库的目标之一是更好地与旧代码进行互操作。特别是,它已经:

    请注意,它仍然是
    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));