如何从数组创建流?


133

目前,每当我需要从数组创建流时,我都会

String[] array = {"x1", "x2"};
Arrays.asList(array).stream();

有一些直接的方法可以从数组创建流吗?

Answers:


201

您可以使用Arrays.stream Eg

Arrays.stream(array);

您也可以使用Stream.of@fge所提到的,它看起来像

public static<T> Stream<T> of(T... values) {
    return Arrays.stream(values);
}

但是note Stream.of(intArray)将返回,Stream<int[]>Arrays.stream(intArr)如果IntStream您传递type数组,则将返回int[]。因此,简而言之,您可以观察两种方法之间的区别,例如

int[] arr = {1, 2};
Stream<int[]> arr1 = Stream.of(arr);

IntStream stream2 = Arrays.stream(arr); 

将原始数组传递给时Arrays.stream,将调用以下代码

public static IntStream stream(int[] array) {
    return stream(array, 0, array.length);
}

当您将原始数组传递给Stream.of以下代码时,将被调用

 public static<T> Stream<T> of(T t) {
     return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false);
 }

因此,您得到不同的结果。

更新:如Stuart Marks的评论所述,的子范围重载Arrays.stream优于使用,Stream.of(array).skip(n).limit(m)因为前者会导致SIZED流,而后者则不会。原因是limit(m)不知道大小是m还是小于m,而Arrays.stream范围检查并知道流的确切大小您可以阅读Arrays.stream(array,start,end) here返回的流实现的源代码,而Stream.of(array).skip().limit()is 可以读取的流实现的源代码。在这种方法内


9
这个答案比较好,因为Arrays.stream具有原始数组的所有重载情况。即Stream.of(new int[]{1,2,3})会给您一个,Stream<int[]>Arrays.stream会给您一个IntStream可能是您想要的。所以+1
user2336315 2015年

3
@Dima我想这是一个品味问题。我的意思是,从某种意义上讲,更好的方法Stream.of可能会给您带来一些惊喜(例如,当您Arrays.asList使用原始数组进行调用并且人们期望List<Integer>返回时:))
user2336315 2015年

3
Arrays.stream支持流式传输数组的范围,IntStream.of但不支持。与此相反,Stream.of是更好的选择,如果你想要一个Stream<int[]>尺寸的1...
霍尔格

4
@Dima Arrays.stream最好使用的子范围重载,Stream.of(array).skip(n).limit(m)因为前者会导致SIZED流,而后者则不会。原因是limit(m)不知道大小是否m小于m,而Arrays.stream范围检查并知道流的确切大小。
Stuart Marks

6
对于有兴趣看这部小剧本的读者,Arrays.stream(array,start,end)返回Stream的实现在此处,而Stream.of(array).skip().limit()返回Stream的实现在此方法内
斯图尔特·马克斯

43

@ sol4me解决方案的替代方案:

Stream.of(theArray)

在this和Arrays.stream():之间的区别在于,如果您的数组是原始类型,它的确会有所不同。例如,如果您这样做:

Arrays.stream(someArray)

这里someArray是一个long[],它会返回一个LongStreamStream.of()另一方面,将返回Stream<long[]>带有单个元素的。


1
@Dima当然可以,但也Arrays.stream()可以使用
fge 2015年

2
好吧,至于溪流,方便!无需打电话*Stream.of()时,你有Arrays.stream()与原始阵列的时候。至于不是真正对象的数组,那是Java,自1.0开始就是如此。沉思于此无济于事
fge 2015年

2
@Dima,您的也是如此;认为Arrays.stream()不方便,认为这很方便。说够了。
fge 2015年

2
@Dima是的,我发现您的说法*Stream.of()更容易谬误;因为这是喜好问题Arrays.stream()对于这种情况,我更喜欢,这通常Stream.of()会更方便,这是错误的做法(Peano代数)。
fge 2015年

3
@Dima:这是一个偏好问题。差异是如此之小,以至于根本没有关系。更具体地说:几个字符的区别就是什么在标准库没有额外导入软件包内容。实际上,手动创建数组而不是varargs重载是没有什么
Jeroen Vannevel 2015年

14
Stream.of("foo", "bar", "baz")

或者,如果您已经有一个数组,也可以执行

Stream.of(array) 

对于基本类型,请使用IntStream.ofLongStream.of等。


我不明白的是,当int[]可以将an 传递给接受varargs的方法时,为什么不Stream.of(intArray)产生a Stream<Integer>而不是Stream<int[]>?此外,是否有任何技术上的原因,为什么有专门用于基元的Stream类?
ass

1
Java基元是怪兽。int[]不像其他数组。这不是一个子类Object[],但它一个子类Object。因此,当您将其传递给时Stream.of,它将作为Object,参数,并获得的流int[]。这就是为什么要为基元设置专门的类的原因之一-如果不从基元数组创建流,将非常痛苦。另一个原因,是一家专业类是更有效,因为不需要招致不Object从拳击开销(转换intInteger以使它看起来像普通的对象)。
迪马

啊,既然int[]是an Object,它将匹配重载方法of(T t),因此返回Stream<int[]>。因此,从理论上讲,如果没有这种方法,我们会得到Stream<Integer>回报吗?还是因为找不到匹配方法而导致编译错误?即int[]不能被视为T...
ass

1
不,我们仍然不会Stream<Integer>那样,因为Stream.of(t ... T) 仍然会以相同的方式匹配。
迪马

0

您也可以通过具有并行选项的低级方法来实现:

更新:使用完整的array.length(不是length-1)。

/** 
 * Creates a new sequential or parallel {@code Stream} from a
 * {@code Spliterator}.
 *
 * <p>The spliterator is only traversed, split, or queried for estimated
 * size after the terminal operation of the stream pipeline commences.
 *
 * @param <T> the type of stream elements
 * @param spliterator a {@code Spliterator} describing the stream elements
 * @param parallel if {@code true} then the returned stream is a parallel
 *        stream; if {@code false} the returned stream is a sequential
 *        stream.
 * @return a new sequential or parallel {@code Stream}
 *
 * <T> Stream<T> stream(Spliterator<T> spliterator, boolean parallel)
 */

StreamSupport.stream(Arrays.spliterator(array, 0, array.length), true)

0

您可以使用Arrays.stream:

Arrays.stream(array); 

这将确保根据您的阵列输入型蒸汽的返回类型,如果它String []再返回Stream<String>,如果int []再返回IntStream

如果您已经知道输入类型数组,那么可以使用像输入类型这样的特定数组 int[]

 IntStream.of(array); 

这将返回Intstream。

在第一个示例中,Java使用方法overloading根据输入类型查找特定方法,而在第二个示例中,您已经知道输入类型并调用特定方法。


0

很少见,但这是最直接的方法

Stream.Builder<String> builder = Stream.builder();
for( int i = 0; i < array.length; i++ )
  builder.add( array[i] );
Stream<String> stream = builder.build();
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.