前面(《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());
}
可以看到,使用流,可以更加简便,也更加直观的表现出代码的功能
1.lambda表达式
《java8 lambda表达式,方法的引用以及构造器的引用》
2.函数式接口
3.stream接口操作
《JAVA8 Stream接口,map操作,filter操作,flatMap操作》
《JAVA8 stream接口 distinct,sorted,peek,limit,skip》
《java8 stream接口 终端操作 forEachOrdered和forEach》
《java8 stream接口 终端操作 toArray操作》
《java8 stream接口 终端操作 min,max,findFirst,findAny操作》
《java8 stream接口终端操作 count,anyMatch,allMatch,noneMatch》
《java8 stream接口 终端操作 collect操作》
4.其他部分