首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >使用流生成short[]

使用流生成short[]
EN

Stack Overflow用户
提问于 2015-06-11 20:20:26
回答 2查看 2.9K关注 0票数 8

在列表中加入一系列连续的短裤的基础上,我尝试生成一系列原始的短裤。事实证明,这比预期要困难得多。

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)生成了一个编译器错误:

代码语言:javascript
复制
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

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

  1. 原始流API没有为short提供实现。
  2. 非原始流API似乎没有提供返回原始数组的机制。

有什么想法吗?

EN

回答 2

Stack Overflow用户

发布于 2015-06-12 03:15:47

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

代码语言:javascript
复制
short[] numbers = IntStreamEx.range(500).toShortArray();
short[] evenNumbers = IntStreamEx.of(numbers).map(x -> x*2).toShortArray();

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

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

票数 2
EN

Stack Overflow用户

发布于 2015-06-12 09:07:04

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

代码语言:javascript
复制
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);
    }
}

然后你就可以用它

代码语言:javascript
复制
short[] array=IntStream.range(0, 500).boxed().collect(ShortCollector.TO_ARRAY);

缺点是Collector只适用于引用类型(因为Generics不支持原始类型),因此您必须求助于boxed(),并且收集器无法利用有关元素数量的信息(如果有可用的话)。因此,在原始数据流上,性能可能比toArray()差得多。

因此,一个追求更高性能的解决方案(我仅限于单线程情况)如下所示:

代码语言:javascript
复制
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();
}

你可以把它当作

代码语言:javascript
复制
short[] array=toShortArray(IntStream.range(0, 500));
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30790665

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档