JDK8 Stream 初識
阿新 • • 發佈:2018-11-07
點這裡
Stream作為jdk8的一種重要特性,我們應該瞭解多一些。
為什麼會有Stream?
在Stream出現之前,我們對集合中的元素進行一些操作需要先遍歷每個元素再進行操作。如:
LinkedHashMap<String, Integer> linkedHashMap = new LinkedHashMap<String, Integer>(); linkedHashMap.put("1", 1); linkedHashMap.put("2", 2); linkedHashMap.put("3", 3); linkedHashMap.put("4", 4); LinkedHashMap<String, Integer> linkedHashMap2 = new LinkedHashMap<String, Integer>(); for (Entry entry : linkedHashMap.entrySet()) { int v = (int)entry.getValue(); linkedHashMap2.put((String)entry.getKey(), v*2); } //結果: //[1=1, 2=2, 3=3, 4=4] //[1=2, 2=4, 3=6, 4=8]
在1.8我們怎麼實現呢?
HashMap<String, Integer> hashMap = (HashMap<String, Integer>) linkedHashMap
.entrySet()
.stream()
.collect(
Collectors.toMap(a -> a.getKey(), a -> a.getValue() * 2));
System.out.println(hashMap.entrySet());
//[1=2, 2=4, 3=6, 4=8]
當你熟練掌握stream用法時,對集合的操作就很方便簡單了。
什麼是Stream?
點這裡
Stream 是用函數語言程式設計方式在集合類上進行復雜操作的工具,其集成了Java 8中的眾多新特性之一的聚合操作,開發者可以更容易地使用Lambda表示式,並且更方便地實現對集合的查詢、遍歷、過濾以及常見計算等。
集合講的是資料,流講的是計算
1> Stream 自己不會儲存元素
2> Stream 不會改變源物件。相反,他們會返回一個持有結果的新Stream
3> Stream 操作是延遲執行的。這意味著他們會等到需要結果的時候才執行
Stream 的操作三個步驟
1> 建立 Stream : 一個數據源 (如 : 集合、陣列), 獲取一個流
2> 中間操作 : 一箇中間操作鏈,對資料來源的資料進行處理
3> 終止操作(終端操作) : 一個終止操作,執行中間操作鏈,併產生結果
建立流:
- collection中擴充套件了default 方法
default Stream<E> stream() {
return StreamSupport.stream(spliterator(), false);
}
default Stream<E> parallelStream() {
return StreamSupport.stream(spliterator(), true);
}
collection.stream()
collection.parallelStream()
- Arrays 類中增加了 stream() 靜態方法
public static <T> Stream<T> stream(T[] array) {
return stream(array, 0, array.length);
}
Stream<Integer> stream2 = Stream.of(1, 2, 3, 4, 5, 6);
int [] a = {1,2,3};
IntStream aStream= Arrays.stream(a);
還有幾種建立方法我沒有掌握,讀者可以點選上面的連線檢視。
Stream的操作
操作型別 | 介面方法 |
---|---|
中間操作 | concat() distinct() filter() flatMap() limit() map() peek()skip() sorted() parallel() sequential() unordered() |
結束操作 | allMatch() anyMatch() collect() count() findAny() findFirst() forEach() forEachOrdered() max() min() noneMatch() reduce() toArray() |
- 1 中間操作
方 法 | 描 述 |
---|---|
切片 | |
filter(Predicate p) | 接收 Lambda , 從流中排除某些元素 |
distinct() | 篩選,通過流所生成元素的 hashCode() 和 equals() 去除重複元素 |
limit(long maxSize) | 保留前n個 |
skip(long n) | 去掉前n個 |
對映 | |
map(Function f) | 接收一個函式作為引數,該函式會被應用到每個元素上,並將其對映成一個新的元素 |
mapToDouble(ToDoubleFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 DoubleStream |
mapToInt(ToIntFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 IntStream |
mapToLong(ToLongFunction f) | 接收一個函式作為引數,該函式會被應用到每個元素上,產生一個新的 LongStream |
flatMap(Function f) | 接收一個函式作為引數,將流中的每個值都換成另一個流,然後把所有流連線成一個流 |
排序 | |
sorted() | 產生一個新流,其中按自然順序排序 |
sorted(Comparator comp) | 產生一個新流,其中按比較器順序排序 |
我們來寫一些例子加深印象,由於是中間方法所以在結尾加了foreach(終止方法)
//原資料
List<String> arrayList =Arrays.asList("1","2","3","3","4","5");
List<String> arrayList2 = Arrays.asList("a", "b", "c", "d", "e", "f");
- 切片型
過濾filter
arrayList.stream().filter(e->e.equals("3")).forEach(System.out::println);
//3 3
刪除重複distinct
arrayList.stream().distinct().forEach(System.out::println);
//1 2 3 4 5
篩選limit
arrayList.stream().limit(3).forEach(System.out::println);
//1 2 3
跳過skip
arrayList.stream().skip(4).forEach(System.out::println);
//4 5
- 對映型
map
arrayList.stream().map(e->e+"A").forEach(System.out::println);
//1A 2A 3A 3A 4A 5A
mapToInt/mapToDouble/mapToLong
arrayList.stream().mapToInt(e -> Integer.parseInt(e))
.filter(e -> e==3).forEach(System.out::println);
//3 3
flatMap
Stream.of(arrayList, arrayList2).flatMap(u -> u.subList(0, 2).stream())
.forEach(System.out::println);
//1 2 a b
- 排序型
sorted
List<String> arrayList3 = Arrays.asList("9", "2", "3", "3", "4", "1");
arrayList3.stream().sorted().forEach(System.out::println);
// 1 2 3 3 4 9
arrayList3.stream().sorted((x, y) -> {
return x.compareTo(y);
}).forEach(System.out::println);
// 1 2 3 3 4 9
我好像對compareto,compareable,comparetor 是不是很懂,明天整理下
- 2 終止操作
方 法 | 描 述 |
---|---|
allMatch(Predicate p) | 檢查是否匹配所有元素 |
anyMatch(Predicate p) | 檢查是否至少匹配一個元素 |
noneMatch(Predicate p) | 檢查是否沒有匹配所有元素 |
findFirst() | 返回第一個元素 |
findAny() | 返回當前流中的任意元素 |
count() | 返回流中元素總數 |
max(Comparator c) | 返回流中最大值 |
min(Comparator c) | 返回流中最小值 |
forEach(Consumer c) | 內部迭代(使用 Collection 介面需要使用者去做迭代,稱為外部迭代。相反, Stream API 使用內部迭代) |
歸納 | |
reduce(T iden, BinaryOperator b) | 可以將流中元素反覆結合起來,得到一個值,返回 T |
reduce(BinaryOperator b) | 可以將流中元素反覆結合起來,得到一個值,返回 Optional |
收集 | |
collect(Collector c) | 將流轉換為其他形式。接收一個 Collector介面的實現,用於給Stream中元素做彙總的方法 |
我們再來對終止操作進行舉例:
reduce 將元素值結合起來
String sum = arrayList.stream().reduce( "",(x,y)->(x+y) );
Optional<String> sum2 = arrayList.stream().reduce((x,y)->(x+y) );
System.out.println( "Sum: "+sum+" Sum2: "+ sum2 );
//Sum: 123345 Sum2: Optional[123345]
anymatch/allmatch/nomatch
boolean flag = arrayList.stream().anyMatch(e->e.equals("1"));
System.err.println(flag);
// true
count
long num = arrayList.stream().count();
System.err.println("num: "+num+" size: "+arrayList.size());
collection
Map<String, List<String> > resultmap=arrayList.stream().collect(Collectors.groupingBy(e->{
if ( e.equals("1") ) {
return "ok";
}
else {
return e;
}
}));
for (Entry entry : resultmap.entrySet()) {
System.out.println(entry.getKey()+" "+entry.getValue());
}
//2 [2]
//3 [3, 3]
//4 [4]
//5 [5]
//ok [1]