java8-Stream

1、概覽

但在當今這個數據大爆炸的時代,在數據來源多樣化、數據海量化的今天,不少時候不得不脫離 RDBMS,或者以底層返回的數據爲基礎進行更上層的數據統計。而 Java 的集合 API 中,僅僅有極少許的輔助型方法,更多的時候是程序員須要用 Iterator 來遍歷集合,完成相關的聚合應用邏輯。這是一種遠不夠高效、笨拙的方法。在 Java 7 中,若是要發現 type 爲 grocery 的全部交易,而後返回以交易值降序排序好的交易 ID 集合,咱們須要這樣寫:html

List<Transaction> groceryTransactions = new Arraylist<>();
for(Transaction t: transactions){
 if(t.getType() == Transaction.GROCERY){
 groceryTransactions.add(t);
 }
}
Collections.sort(groceryTransactions, new Comparator(){
 public int compare(Transaction t1, Transaction t2){
 return t2.getValue().compareTo(t1.getValue());
 }
});
List<Integer> transactionIds = new ArrayList<>();
for(Transaction t: groceryTransactions){
 transactionsIds.add(t.getId());
}

可是若是是stream:java

List<Integer> transactionsIds = transactions.parallelStream().
 filter(t -> t.getType() == Transaction.GROCERY).
 sorted(comparing(Transaction::getValue).reversed()).
 map(Transaction::getId).
 collect(toList());

2、生成Stream的方式

有多種方式生成 Stream Source:程序員

  • 從 Collection 和數組:
    • Collection.stream()
    • Collection.parallelStream()
    • Arrays.stream(T array) or Stream.of()
    • 從 BufferedReader
    • java.io.BufferedReader.lines()
  • 靜態工廠
    • java.util.stream.IntStream.range()
    • java.nio.file.Files.walk()
  • 本身構建
    • java.util.Spliterator
  • 其它
    • Random.ints()
    • BitSet.stream()
    • Pattern.splitAsStream(java.lang.CharSequence)
    • JarFile.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:安全

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);

3、轉爲其餘數據結構

// 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();

4、流的操做

  • Intermediate:中間操做
    • map (mapToInt, flatMap 等) : 把元素映射成另外一個元素,好比把裏面全部的元素都轉成大寫。
      List<String> output = wordList.stream().
      	map(String::toUpperCase).
      	collect(Collectors.toList());
- filter:過濾全部元素,接受一個返回boolean的表達式
	- distinct:去重
	- sorted:對 Stream 的排序經過 sorted 進行,它比數組的排序更強之處在於你能夠首先對 Stream 進行各種 map、filter、limit、skip 甚至 distinct 來減小元素數量後,再排序,這能幫助程序明顯縮短執行時間。
	sorted(Comparator<? super T> comparator);接受一個Comparator,
	
	如:sorted((p1, p2) -> p1.getName().compareTo(p2.getName()))
	- peek:  對每一個元素執行操做並返回一個新的 Stream, forEach有一樣的功能,可是foreach是一個終端操做
	- limit、
	- skip:跳過前X個元素
	- parallel、
	- sequential、
	- unordered

- Terminal:終端操做
	- forEach : 接受一個表達式,對這個全部元素執行這個表達式
	forEachOrdere
	toArray
	- reduce:提供一個種子和一個表達式,從種子和全部元素依次執行這個表達式,每次執行的結果都是後一次表達式執行的種子。也能夠沒有種子,則會返回一個Optional。從這個意義上說,字符串拼接、數值的 sum、min、max、average 都是特殊的 reduce。例如 Stream 的 sum 就至關於:
	```java
// 字符串鏈接,concat = "ABCD"
String concat = Stream.of("A", "B", "C", "D").reduce("", String::concat); 
// 求最小值,minValue = -3.0
double minValue = Stream.of(-1.5, 1.0, -3.0, -2.0).reduce(Double.MAX_VALUE, Double::min); 
// 求和,sumValue = 10, 有起始值
int sumValue = Stream.of(1, 2, 3, 4).reduce(0, Integer::sum);
// 求和,sumValue = 10, 無起始值
sumValue = Stream.of(1, 2, 3, 4).reduce(Integer::sum).get();
// 過濾,字符串鏈接,concat = "ace"
concat = Stream.of("a", "B", "c", "D", "e", "F").
 filter(x -> x.compareTo("Z") > 0).
 reduce("", String::concat);
Integer sum = integers.reduce(0, Integer::sum);
- collect : java.util.stream.Collectors 類的主要做用就是輔助進行各種有用的 reduction 操做,

例如轉變輸出爲 Collection : collect(Collectors.toList()); 把 Stream 元素進行歸組 : groupingBy/partitioningBy。
- min:找到最小值
- max:找到最大值
- count
- anyMatch
- allMatch
- noneMatch
- findFirst
- findAny
- iterator
  • Short-circuiting:短路操做
    • anyMatch
    • allMatch
    • noneMatch
      • allMatch:Stream 中所有元素符合傳入的 predicate,返回 true
      • anyMatch:Stream 中只要有一個元素符合傳入的 predicate,返回 true
      • noneMatch:Stream 中沒有一個元素符合傳入的 predicate,返回 true
    • findFirst:返回第一個元素或者空,返回值是Optional !!!
    String optional = null;
        Optional.ofNullable(optional).ifPresent(String::toUpperCase); //由於這裏是空值,因此直接跳過
        System.out.println("aa");  //這個程序只是打印了這個aa
- findAny: 返回流中的任意一個值
	- limit: 返回流中的前X個元素


# 5、Java8 parallelStream是線程不安全的!
	解決方案:
		https://www.cnblogs.com/puyangsky/p/7608741.html
		總結就是paralleStream裏直接去修改變量是非線程安全的,可是採用collect和reduce操做就是知足線程安全的了(前提是不干擾源數據,而且與數據處理的順序無關)。



# 6、CompletableFuture相關教程
	1. https://colobu.com/2016/02/29/Java-CompletableFuture/
	2. http://songkun.me/2018/05/27/2018-05-26-java8-completablefuture/
相關文章
相關標籤/搜索