java8 Stream-创建流的几种方式

前面(《java8 Stream接口简介》),我们已经对stream这个接口,做了简单的介绍,下面,我们用几个案例,来看看流的几种创建方式

                String[] dd = { "a", "b", "c" };
		Arrays.stream(dd).forEach(System.out::print);// abc
		System.out.println();
		Stream.of(dd).forEach(System.out::print);// abc
		System.out.println();
		Arrays.asList(dd).stream().forEach(System.out::print);// abc
		System.out.println();
		Stream.iterate(0, x -> x + 1).limit(10).forEach(System.out::print);// 0123456789
		System.out.println();
		Stream.generate(() -> "x").limit(10).forEach(System.out::print);// xxxxxxxxxx

1.Arrays.stream,我们可以通过Arrays的静态方法,传入一个泛型数组,创建一个流

2.Stream.of,我们可以通过Stream的静态方法,传入一个泛型数组,或者多个参数,创建一个流,这个静态方法,也是调用了Arrays的stream静态方法,如下

  @SafeVarargs
    @SuppressWarnings("varargs") // Creating a stream from an array is safe
    public static<T> Stream<T> of(T... values) {
        return Arrays.stream(values);
    }

3.Collection.stream,可以用过集合的接口的默认方法,创建一个流;使用这个方法,包括继承Collection的接口,如:Set,List,Map,SortedSet 等等,详细的,可以看Collection接口上的定义注释,如下

/**
 * @author Josh Bloch
 * @author Neal Gafter
 * @see Set
 * @see List
 * @see Map
 * @see SortedSet
 * @see SortedMap
 * @see HashSet
 * @see TreeSet
 * @see ArrayList
 * @see LinkedList
 * @see Vector
 * @see Collections
 * @see Arrays
 * @see AbstractCollection
 * @since 1.2
 */
public interface Collection<E> extends Iterable<E> {
	default Stream<E> stream() {
        return StreamSupport.stream(spliterator(), false);
    }
}

4.Stream.iterate,是Stream接口下的一个静态方法,从名字也可以看出,这个静态方法,是以迭代器的形式,创建一个数据流,具体的静态方法定义如下:

 public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f) {
        Objects.requireNonNull(f);
        final Iterator<T> iterator = new Iterator<T>() {
            @SuppressWarnings("unchecked")
            T t = (T) Streams.NONE;

            @Override
            public boolean hasNext() {
                return true;
            }

            @Override
            public T next() {
                return t = (t == Streams.NONE) ? seed : f.apply(t);
            }
        };
        return StreamSupport.stream(Spliterators.spliteratorUnknownSize(
                iterator,
                Spliterator.ORDERED | Spliterator.IMMUTABLE), false);
    }

静态方法定义以及代码中,可以看到,传入两个参数,一个泛型T对象,表示数据的起始,一个函数式接口UnaryOperator(不知道这个接口的,JAVA8 UnaryOperator接口,有详细介绍),从迭代器hasNext中,可以看到,返回一直为true,表示迭代器,会一直执行下去,创建的数据集合的值为泛型T对象;这样一直创建无限个对象的流,也成为无限流;

5.Stream.generate,也是stream中的一个静态方法,静态方法定义如下:

public static<T> Stream<T> generate(Supplier<T> s) {
        Objects.requireNonNull(s);
        return StreamSupport.stream(
                new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false);
    }

从静态方法定义中,可以看到,传入一个函数式接口Supplier(不知道这个接口是什么意义的,可以移步这边,JAVA8 Supplier接口有详细介绍);这个静态方法,也是无限生成对象的集合流,也是一个无限流;


最后介绍下,1-3,是根据具体的数组或者集合对象,创建的流,在创建流之前,这些对象的大小(长度)已经确认,所以这个种方式的流,也被成为有限流,而4-5中,创建流的方式,是无限大小的流(generate 最大是Long.MAX_VALUE),也被成为无限流,那么我们不可能就这样放任对象被无限创建,直到内存溢出,这样的无限流,也是配合limit使用,指定这个流生成的元素的个数,对于无限流,下面再简单讲个案例,使用传统的方式和无限流的方式,创建一个固定大小的ArrayList,这样大家也会有比较清楚的认识;

应用场景:我们再做B端系统的时候,会遇到很多的统计类的需求,会用到百度的echarts插件,比如曲线图,在x抽,固定的况下(按月统计 1号-31号,或者按年统计1月-12月,或者按天24个小时的刻度),那么我就需要创建一个这个数组,或者集合,代码如下:

public static void main(String[] args) {
		System.out.println(buildList(100));
		System.out.println(buildIterate(100));
	}

	public static List<Integer> buildList(final int size) {
		List<Integer> list = new ArrayList<>(size);
		for (int i = 1; i <= size; i++) {
			list.add(i);
		}
		return list;
	}

	public static List<Integer> buildIterate(final int size) {
		return Stream.iterate(1, x -> ++x).limit(size).collect(Collectors.toList());
	}
可以看到,使用流,可以更加简便,也更加直观的表现出代码的功能

上一篇《java8 Stream接口简介》           下一篇《JAVA8 stream接口 中间操作和终端操作》

猜你喜欢

转载自blog.csdn.net/qq_28410283/article/details/80633710