Java 8如何流到数组大小的工作原理?

时间:2015-02-11 20:30:04

标签: java-8 java-stream

String[] stringArray = streamString.toArray(size -> new String[size]);

如何自动将大小视为流的大小?

2 个答案:

答案 0 :(得分:6)

Stream API围绕Spliterator形成,characteristics是迭代器的高级形式。这些可以报告某些estimated,允许优化Stream将适用的操作。他们还可能会报告预期的元素数量,exactSIZEDSpliterator如果事先知道元素的数量,则会报告JB Nizet explained特征。

在给定封装操作的情况下,您可以使用以下方法测试Stream对其元素的知识:

public static <T> Stream<T> printProperties(String op, Stream<T> s) {
    System.out.print("characteristics after "+op+": ");
    Spliterator<T> sp=s.spliterator();
    int characteristics=sp.characteristics();
    if(characteristics==0) System.out.println("0");
    else {
        String str;
        for(;;) {
            int flag=Integer.highestOneBit(characteristics);
            switch(flag) {
                case ORDERED: str="ORDERED"; break;
                case DISTINCT: str="DISTINCT"; break;
                case SORTED: str="SORTED"; break;
                case SIZED: str="SIZED"; break;
                case NONNULL: str="NONNULL"; break;
                case IMMUTABLE: str="IMMUTABLE"; break;
                case CONCURRENT: str="CONCURRENT"; break;
                case SUBSIZED: str="SUBSIZED"; break;
                default: str=String.format("0x%X", flag);
            }
            characteristics-=flag;
            if(characteristics==0) break;
            System.out.append(str).append('|');
        }
        System.out.println(str);
    }
    return StreamSupport.stream(sp, s.isParallel());
}

您可以使用它来了解某些操作如何影响有关元素的知识。例如,当您将此方法与以下测试程序一起使用时:

Stream<Object> stream;
stream=printProperties("received from TreeSet", new TreeSet<>().stream() );
stream=printProperties("applying map", stream.map(x->x) );
stream=printProperties("applying distinct", stream.distinct() );
stream=printProperties("filtering", stream.filter(x->true) );
stream=printProperties("applying sort", stream.sorted() );
stream=printProperties("requesting unordered", stream.unordered() );

System.out.println();

stream=printProperties("received from varargs array", Stream.of("foo", "bar") );
stream=printProperties("applying sort", stream.sorted() );
stream=printProperties("applying map", stream.map(x->x) );
stream=printProperties("applying distinct", stream.distinct() );
stream=printProperties("requesting unordered", stream.unordered() );

System.out.println();

printProperties("ConcurrentHashMap.keySet().stream()",
    new ConcurrentHashMap<>().keySet().stream() );

它会打印出来:

characteristics after received from TreeSet: SIZED|ORDERED|SORTED|DISTINCT
characteristics after applying map: SIZED|ORDERED
characteristics after applying distinct: ORDERED|DISTINCT
characteristics after filtering: ORDERED|DISTINCT
characteristics after applying sort: ORDERED|SORTED|DISTINCT
characteristics after requesting unordered: SORTED|DISTINCT

characteristics after received from varargs array: SUBSIZED|IMMUTABLE|SIZED|ORDERED
characteristics after applying sort: SUBSIZED|SIZED|ORDERED|SORTED
characteristics after applying map: SUBSIZED|SIZED|ORDERED
characteristics after applying distinct: ORDERED|DISTINCT
characteristics after requesting unordered: DISTINCT

characteristics after ConcurrentHashMap.keySet().stream(): CONCURRENT|NONNULL|DISTINCT

作为the documentation says,如果流预先不知道大小,则必须使用策略来收集可能包括重新分配数组的元素。正如{{3}}:

  

...使用提供的生成器函数来分配返回的数组以及分区执行或调整大小可能需要的任何其他数组

答案 1 :(得分:3)

size -> new String[size]

是一个lambda,它是IntFunction<A[]> generator的一个实例,因为the method的签名是

<A> A[] toArray(IntFunction<A[]> generator)

因此,该行创建了一个IntFunction实例,并将其作为参数传递给流。流是调用函数的流(即调用方法apply(int)),因此流是将大小作为参数传递的流。流知道它自己的大小。