java8函數式編程(四)

相關鏈接:

java8函數式編程(一)
java8函數式編程(二)
java8函數式編程(三)

  其中(一)是在沒有開始瞭解java8新特性之前實際遇到的一個問題,使用for循環實現的代碼很繁瑣,於是嘗試使用新的編碼風格,最後很不完美的實現了需求。在進一步學習後,在(二)中完美實現,並對List常用的操作做了一個總結。最後在(三)中對並行化流與並行化數組的操作簡單歸納。
  本節主要是對java8流處理一個總結以及一些細節的補充。另外,學習資料主要參考《Java8實戰》與《Java8函數式編程》兩本書籍。


Stream API

優點:

1 聲明性 – 簡潔、易讀
2 可複合 – 靈活組合
3 可並行 – 高性能

常用操作:
1 篩選
filter  過濾
distinct  去重
limit   截斷
skip   跳過
2 映射
map   轉換
flatMap   扁平化轉換
3 查找與匹配
anyMatch   至少有一個滿足
allMatch   所有都滿足
noneMatch   沒有一個滿足
findAny   返回任意一個
findFrist   返回第一個
4 歸約
reduce   計算
count   元素個數
5 數值流
mapToInt     IntStream
mapToDouble  DoubleStream
max    最大
min    最小
average   平均
boxed   數值流裝箱
range   範圍內(不包括end)
reageClosed  範圍內(包括end)
6 構建流
of
iterate
generate
7 收集器
collect

數值操作

從1到20間的奇數

IntStream.rangeClosed(1, 20)
                .filter(n -> n%2 != 0)
                .forEach(System.out::println);

100以內奇數的和

int sum = IntStream.range(1, 100)
                .filter(n -> n % 2 != 0)
                .sum();

斐波那契數列(前20位)

Stream.iterate(new int[]{0,1}, n -> new int[]{n[1], n[0] + n[1]})
                .limit(20)
                .map(n -> n[0])
                .forEach(System.out::println);

collect收集器

準備數據依然使用List<Frog>,frog的屬性有name名稱,age年齡,color顏色,size體積。

        List<Frog> list = new ArrayList<>();
        list.add(new Frog("one", 2 , "red", 5.1));
        list.add(new Frog("two", 3 , "red", 5.0));
        list.add(new Frog("three", 2 , "blue", 5.5));
        list.add(new Frog("four", 1 , "blue", 5.3));
        list.add(new Frog("five", 5 , "yellow", 5.1));
        list.add(new Frog("six", 3 , "yellow", 5.2));

collect方法參數Collector。Collector接口中方法實現對流執行的操作,Collectors實現類提供很多靜態方法,下面是對這些靜態方法的說明。
爲了代碼簡潔,導入Collectors類中所有方法:

import static java.util.stream.Collectors.*;

summaryStatistics

該方法可以一次性獲取到數量、總和、最大值、最小值和平均數

DoubleSummaryStatistics summaryStatistics = frogs.stream()
                .collect(summarizingDouble(Frog::getSize));
System.out.println(summaryStatistics);

打印結果

DoubleSummaryStatistics{count=6, sum=31.200000, min=5.000000, average=5.200000, max=5.500000}

也可以直接通過summaryStatistics 的getter方法獲取某一項。

joining

字符串的連接,方法重載

String names = frogs.stream()
                .map(Frog::getName)
                .collect(joining(" ", "[", "]"));

打印結果

[one two three four five six]

groupingBy

1、分組與多級分組

Map<String, List<Frog>> map = frogs.stream()
                .collect(groupingBy(Frog::getColor));

Map<String, Map<Volume, List<Frog>>> map1 = frogs.stream()
                .collect(groupingBy(Frog::getColor,
                        groupingBy(frog -> {
                            if (frog.getSize() < 5.2) {
                                return Volume.SMALL;
                            } else {
                                return Volume.BIG;
                            }
                        })));
                    
public enum Volume {
        BIG,
        SMALL
}

打印結果

{
 red=[Frog{name='one', age=2, color='red', size=5.1}, Frog{name='two', age=3, color='red', size=5.0}],
 blue=[Frog{name='three', age=2, color='blue', size=5.5}, Frog{name='four', age=1, color='blue', size=5.3}],
 yellow=[Frog{name='five', age=5, color='yellow', size=5.1}, Frog{name='six', age=3, color='yellow', size=5.2}]
 }

{
 red={
 	SMALL=[Frog{name='one', age=2, color='red', size=5.1}, Frog{name='two', age=3, color='red', size=5.0}]
 	},
 blue={
 	BIG=[Frog{name='three', age=2, color='blue', size=5.5}, Frog{name='four', age=1, color='blue', size=5.3}]
 	}, 
 yellow={
 	BIG=[Frog{name='six', age=3, color='yellow', size=5.2}], 
 	SMALL=[Frog{name='five', age=5, color='yellow', size=5.1}]
 	}
}

groupingBy第二個參數可以使用mapping方法。例:

Map<String, HashSet<Volume>> map4 = frogs.stream()
                .collect(groupingBy(Frog::getColor,
                        mapping(frog -> {
                            if (frog.getSize() < 5.2) {
                                return Volume.SMALL;
                            } else {
                                return Volume.BIG;
                            }
                        }, toCollection(HashSet::new))));

2、分組後的數據操作,比如按顏色分組,求每組中size最大的元素

Map<String, Frog> map2 = frogs.stream()
                .collect(groupingBy(Frog::getColor,
                        collectingAndThen(minBy(Comparator.comparingDouble(Frog::getSize)), Optional::get)));

等價的寫法

Map<String, Frog> map3 = frogs.stream()
                .collect(toMap(Frog::getColor,
                        Function.identity(),
                        BinaryOperator.minBy(Comparator.comparingDouble(Frog::getSize))));

Function.identity():返回一個總是返回其輸入參數的函數

partitioningBy

分區,分組的特殊情況,將數據分爲true和false兩組

Map<Boolean, Long> map = frogs.stream()
                .collect(partitioningBy(t -> t.getAge() > 1, counting()));

打印結果

{false=1, true=5}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章