先说点题外话:很多读者工做几年后,仍然在使用Java7以前版本的方法,对于Java8版本的新特性,甚至是Java7的新特性几乎没有接触过。真心想对这些读者说:你真的须要了解下Java8甚至之后版本的新特性了。java
今天,一名读者出去面试,面试官问他:说说Java8中建立Stream流有哪几种方式?他居然没回答上来!!面试
Java8中有两大最为重要的改变。第一个是 Lambda 表达式;另一个则是 Stream API(java.util.stream.*)。数据库
Stream 是 Java8 中处理集合的关键抽象概念,它能够指定你但愿对集合进行的操做,能够执行很是复杂的查找、过滤和映射数据等操做。使用Stream API 对集合数据进行操做,就相似于使用 SQL 执行的数据库查询。也可使用 Stream API 来并行执行操做。简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。数组
流(Stream) 究竟是什么呢?微信
能够这么理解流:流就是数据渠道,用于操做数据源(集合、数组等)所生成的元素序列。app
“集合讲的是数据,流讲的是计算! ”dom
注意:ide
①Stream 本身不会存储元素。学习
②Stream 不会改变源对象。相反,他们会返回一个持有结果的新Stream。测试
③Stream 操做是延迟执行的。这意味着他们会等到须要结果的时候才执行。
1.建立 Stream
一个数据源(如: 集合、数组), 获取一个流。
2.中间操做
一个中间操做链,对数据源的数据进行处理。
3.终止操做(终端操做)
一个终止操做,执行中间操做链,并产生结果 。
这里,建立测试类TestStreamAPI1,全部的操做都是在TestStreamAPI1类中完成的。
(1)经过Collection系列集合提供的stream()方法或者parallelStream()方法来建立Stream。
在Java8中,Collection 接口被扩展,提供了两个获取流的默认方法,以下所示。
default Stream<E> stream() { return StreamSupport.stream(spliterator(), false); } default Stream<E> parallelStream() { return StreamSupport.stream(spliterator(), true); }
其中,stream()方法返回一个顺序流,parallelStream()方法返回一个并行流。
咱们可使用以下代码方式来建立顺序流和并行流。
List<String> list = new ArrayList<>(); list.stream(); list.parallelStream();
(2)经过Arrays中的静态方法stream()获取数组流。
Java8 中的 Arrays类的静态方法 stream() 能够获取数组流 ,以下所示。
public static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); }
上述代码的的做用为:传入一个泛型数组,返回这个泛型的Stream流。
除此以外,在Arrays类中还提供了stream()方法的以下重载形式。
public static <T> Stream<T> stream(T[] array) { return stream(array, 0, array.length); } public static <T> Stream<T> stream(T[] array, int startInclusive, int endExclusive) { return StreamSupport.stream(spliterator(array, startInclusive, endExclusive), false); } public static IntStream stream(int[] array) { return stream(array, 0, array.length); } public static IntStream stream(int[] array, int startInclusive, int endExclusive) { return StreamSupport.intStream(spliterator(array, startInclusive, endExclusive), false); } public static LongStream stream(long[] array) { return stream(array, 0, array.length); } public static LongStream stream(long[] array, int startInclusive, int endExclusive) { return StreamSupport.longStream(spliterator(array, startInclusive, endExclusive), false); } public static DoubleStream stream(double[] array) { return stream(array, 0, array.length); } public static DoubleStream stream(double[] array, int startInclusive, int endExclusive) { return StreamSupport.doubleStream(spliterator(array, startInclusive, endExclusive), false); }
基本上可以知足基本将基本类型的数组转化为Stream流的操做。
咱们能够经过下面的代码示例来使用Arrays类的stream()方法来建立Stream流。
Integer[] nums = new Integer[]{1,2,3,4,5,6,7,8,9}; Stream<Integer> numStream = Arrays.stream(nums);
(3)经过Stream类的静态方法of()获取数组流。
可使用静态方法 Stream.of(), 经过显示值建立一个流。它能够接收任意数量的参数。
咱们先来看看Stream的of()方法,以下所示。
public static<T> Stream<T> of(T t) { return StreamSupport.stream(new Streams.StreamBuilderImpl<>(t), false); } @SafeVarargs @SuppressWarnings("varargs") public static<T> Stream<T> of(T... values) { return Arrays.stream(values); }
能够看到,在Stream类中,提供了两个of()方法,一个只须要传入一个泛型参数,一个须要传入一个可变泛型参数。
咱们可使用下面的代码示例来使用of方法建立一个Stream流。
Stream<String> strStream = Stream.of("a", "b", "c");
(4)建立无限流
可使用静态方法 Stream.iterate() 和Stream.generate(), 建立无限流。
先来看看Stream类中iterate()方法和generate()方法的源码,以下所示。
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); } public static<T> Stream<T> generate(Supplier<T> s) { Objects.requireNonNull(s); return StreamSupport.stream( new StreamSpliterators.InfiniteSupplyingSpliterator.OfRef<>(Long.MAX_VALUE, s), false); }
经过源码能够看出,iterate()方法主要是使用“迭代”的方式生成无限流,而generate()方法主要是使用“生成”的方式生成无限流。咱们可使用下面的代码示例来使用这两个方法生成Stream流。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2); intStream.forEach(System.out::println);
运行上述代码,会在终端一直输出偶数,这种操做会一直持续下去。若是咱们只须要输出10个偶数,该如何操做呢?其实也很简单,使用Stream对象的limit方法进行限制就能够了,以下所示。
Stream<Integer> intStream = Stream.iterate(0, (x) -> x + 2); intStream.limit(10).forEach(System.out::println);
Stream.generate(() -> Math.random()).forEach(System.out::println);
上述代码一样会一直输出随机数,若是咱们只须要输出5个随机数,则只须要使用limit()方法进行限制便可。
Stream.generate(() -> Math.random()).limit(5).forEach(System.out::println);
(5)建立空流
在Stream类中提供了一个empty()方法,以下所示。
public static<T> Stream<T> empty() { return StreamSupport.stream(Spliterators.<T>emptySpliterator(), false); }
咱们可使用Stream类的empty()方法来建立一个空Stream流,以下所示。
Stream<String> empty = Stream.empty();
若是以为文章对你有点帮助,请微信搜索并关注「 冰河技术 」微信公众号,跟冰河学习Java8新特性。
最后,附上Java8新特性核心知识图,祝你们在学习Java8新特性时少走弯路。