Stream(Java 8)

Java 8 中的 Stream 是對集合(Collection)對象功能的加強,它專一於對集合對象進行各類很是便利、高效的聚合操做(aggregate operation),或者大批量數據操做 (bulk data operation)。 它提供串行和並行兩種模式進行匯聚操做,併發模式可以充分利用多核處理器的優點,使用fork/join並行方式來拆分任務和加速處理過程。數組

###前言安全

Stream 就如同一個迭代器(Iterator),單向,不可往復,數據只能遍歷一次。

流的構成:
	獲取一個數據源(source)→ 數據轉換 → 執行操做獲取想要的結果。
	每次轉換原有 Stream 對象不改變,返回一個新的 Stream 對象(能夠有屢次轉換)。


轉換操做是lazy(惰性求值,只能迭代一次):

	只有在Terminal操做執行時,纔會一次性執行。

	Stream 裏有個操做函數的集合,每次轉換操做就是把轉換函數放入這個集合中。

	在 Terminal 操做的時候循環 Stream 對應的集合,而後對每一個元素執行全部的函數。

###構造流的幾種常見方法數據結構

1. Individual values

	Stream stream = Stream.of("a", "b", "c");

2. Arrays

	String [] strArray = new String[]{"a", "b", "c"};
	stream = Stream.of(strArray);
	stream = Arrays.stream(strArray);

3. Collections

	List<String> list = Arrays.asList(strArray);
	stream = list.stream();

文件生成流:
	Stream<String> stream = Files.lines(Paths.get("data.txt"));

###流轉換爲其它數據結構併發

1. Array

	String[] strArray1 = stream.toArray(String[]::new);

2. Collection

	List<String> list1 = stream.collect(Collectors.toList());
	List<String> list2 = stream.collect(Collectors.toCollection(ArrayList::new));
	Set set1 = stream.collect(Collectors.toSet());
	Stack stack1 = stream.collect(Collectors.toCollection(Stack::new));

3. String

	String str = stream.collect(Collectors.joining()).toString();

###流的操做dom

當把一個數據結構包裝成 Stream 後,就要開始對裏面的元素進行各種操做了。常見的操做能夠歸類以下。


中間操做:
	Intermediate(主要是打開流,作出某種程度的數據映射/過濾,而後返回一個新的流)

	map(mapToInt, flatMap)、 
	filter、 distinct、 sorted、 
	peek、 limit、 skip、 parallel、 sequential、 unordered

	.filter(person -> person.getAge() == 20)	過濾器

	.distinct()	去除重複元素,這個方法是經過類的 equals 方法來判斷兩個元素是否相等的

	.sorted()(流中的元素的類實現了 Comparable 接口) / sorted((p1, p2) -> p1.getAge() - p2.getAge())	排序
	.sorted(Comparator.comparingInt(Person::getAge))

	.limit(long n)	返回前 n 個元素

	.skip(long n)	去除前 n 個元素

	.map(T -> R)	將流中的每個元素 T 映射爲 R(相似類型轉換)
	.map(Person::getName)

	.flatMap(T -> Stream<R>)	將流中的每個元素 T(數組) 映射爲一個流,再把每個流鏈接成爲一個流
	.flatMap(Arrays::stream)


結束操做:
	Terminal(流的最後一個操做)

	forEach、 forEachOrdered、 
	toArray、 reduce、 collect、 min、 max、 
	count、 anyMatch、 allMatch、 noneMatch、 findFirst、 findAny、 iterator

	boolean b = list.stream().anyMatch(person -> person.getAge() == 20);	判斷是否有匹配條件的元素

	.allMatch(T -> boolean)	是否全部元素都符合匹配條件

	.reduce((T, T) -> T) 和 reduce(T, (T, T) -> T)	用於組合流中的元素,如求和,求積,求最大值等
	.reduce(0, Integer::sum)
	reduce 第一個參數 0 表明起始值爲 0

	.count()	返回流中元素個數,結果爲 long 類型

	.collect()	收集方法

		最經常使用的方法,把流中全部元素收集到一個 List Set Collection 中

			toList()
			toSet()
			toCollection()
			toMap()

		joining() 鏈接字符串

		counting()	計算總和

###數值流ide

Stream<Integer> 類型,而每一個 Integer 都要拆箱成一個原始類型再進行 sum 方法求和,這樣大大影響了效率。

針對這個問題 Java 8 有良心地引入了數值流 IntStream, DoubleStream, LongStream。


三種對應的包裝類型 Stream:

	IntStream、LongStream、DoubleStream

IntStream.of(new int[]{1, 2, 3}).forEach(System.out::println);

IntStream.range(1, 3).forEach(System.out::println);	半開區間[)

IntStream.rangeClosed(1, 3).forEach(System.out::println);	閉區間[]


流轉換爲數值流:
	mapToInt(T -> int) : return IntStream
	mapToDouble(T -> double) : return DoubleStream
	mapToLong(T -> long) : return LongStream

數值流轉換爲流:
	Stream<Integer> stream = intStream.boxed();

數值流方法:
	sum()
	max()
	min()
	average()

###並行流(必須是線程安全的)函數

Stream.of(list).parallel();

###無限長度的流線程

generator:
	generator方法,返回一個無限長度的Stream,其元素由Supplier接口的提供。

	在Supplier是一個函數接口,只封裝了一個get()方法,其用來返回任何泛型的值。

		- generate(Supplier<T> s):返回一個無限長度的Stream

		示例:
		
		1. Stream<Double> generateA = Stream.generate(new Supplier<Double>() {
		     @Override
		     public Double get() {
		         return Math.random();
		     }
		   });
		
		2. Stream<Double> generateB = Stream.generate(()->Math.random());
		3. Stream<Double> generateC = Stream.generate(Math::random);
		
iterate
	iterate方法,其返回的也是一個無限長度的Stream。

	與generate方法不一樣的是,其是經過函數f迭代對給指定的元素種子而產生無限連續有序Stream,
	其中包含的元素能夠認爲是:seed,f(seed),f(f(seed))無限循環。
		
		- iterate(T seed, UnaryOperator<T> f)
		
		示例:
		
			Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);
			      // 打印結果:1,2,3,4,5,6,7,8,9,10 
		
			上面示例,種子爲1,也可認爲該Stream的第一個元素,
			經過f函數來產生第二個元素。
			接着,第二個元素,做爲產生第三個元素的種子,從而產生了第三個元素,
			以此類推下去。
			須要注意的是,該Stream也是無限長度的,
			應該使用filter、limit等來截取Stream,不然會一直循環下去。
相關文章
相關標籤/搜索