前面(《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表達式簡介》
《java8 lambda表達式,方法的引用以及構造器的引用》
2.函數式接口
《java8 函數式接口簡介》
《JAVA8 Function接口以及同類型的特化的接口》
《JAVA8 Consumer接口》
《JAVA8 Supplier接口》
《JAVA8 UnaryOperator接口》
《JAVA8 BiConsumer 接口》
3.stream接口操作
《java8 Stream接口簡介》
《 java8 Stream-建立流的幾種方式》
《JAVA8 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 srteam接口終端操作reduce操作》
《java8 stream接口 終端操作 collect操作》
4.其他部分
《java8 Optional靜态類簡介,以及用法》