收集器

一種通用的、從流生成複雜值的結構,只要把它傳給collect方法,全部的流就均可以使用它了。java

標準類庫已經提供了一些有用的收集器,下面示例代碼中的收集器都是從java.util.stream.Collectors類中導入的。優化

轉換成其餘集合

使用Collectors.toList,還有toSet、toCollection等,這裏不須要指定具體的類型,Stream類庫在背後自動挑選合適的類型。spa

若是須要指定具體的類型,可使用toCollection,用定製的集合收集元素code

// 使用TreeSet收集元素
Stream.of(1, 2, 3).collect(Collectors.toCollection(TreeSet::new));

轉換成值

能夠利用收集器讓流生成一個值對象

// 計算每一個元素加1後的平均值
Stream.of(1, 2, 3).collect(Collectors.averagingInt(number -> number + 1));

數據分塊

另一種經常使用的流操做是將其分解爲兩個集合。可使用收集器partitioningBy,它接收一個流,並將其分紅兩部分(使用Predicate對象判斷一個元素應該屬於哪一個部分,並根據布爾值返回一個map到列表)ci

// 分別找出奇數和偶數
Map<Boolean, List<Integer>> collect = 
                Stream.of(1, 2, 3, 4).collect(Collectors.partitioningBy(number -> number % 2 == 0));

數據分組

數據分組是一種更天然的分割數據操做,與將數據分紅true和false不一樣,可使用任意值對數據分組。使用groupingBy能夠對流進行分組字符串

List<Track> tracks = Arrays.asList(new Track("Bakal", 524),
                new Track("Violets for Your Furs", 378),
                new Track("Bakal", 451));

// 根據名稱來分組
Map<String, List<Track>> collect = 
                tracks.stream().collect(Collectors.groupingBy(track -> track.getName()));

// 使用方法應用優化
Map<String, List<Track>> collect = 
                tracks.stream().collect(Collectors.groupingBy(Track::getName));

字符串

不少時候,收集流中的數據都是爲了在最後生成一個字符串。可使用joiningget

List<Track> tracks = Arrays.asList(new Track("Bakal", 524),
                new Track("Violets for Your Furs", 378),
                new Track("Bakal", 451));

// 使用map提取名稱,使用joining獲得一個字符串,容許用戶指定分割符、前綴、後綴
String collect = tracks.stream()
                .map(Track::getName)
                .collect(Collectors.joining(", ", "[", "]"));

組合收集器

可使用第二個收集器,用以收集最終結果的一個子集,這些收集器叫作下游收集器。收集器是生成最終結果的一劑配方,下游收集器是生成部分結果的配方,主收集器中會用到下游收集器。it

List<Track> tracks = Arrays.asList(new Track("Bakal", 524),
                new Track("Violets for Your Furs", 378),
                new Track("Bakal", 451));

// 計算每一個分組下的數量
Map<String, Long> collect =
                tracks.stream()
                        .collect(Collectors.groupingBy(Track::getName, Collectors.counting()));

自定義收集器

除此以外,還能夠自定義收集器,這裏再也不展開io

練習

使用Map的computeIfAbsent方法高效計算斐波那契數列

public class Fibonacci {

    private static final Map<Integer,Long> cache;

    static {
        cache = new HashMap<>();
        cache.put(0, 0L);
        cache.put(1, 1L);
    }

    public static long fibonacci(int x) {
        // 當cache中有時,則直接計算,若是沒有則計算並放入cache中
        return cache.computeIfAbsent(x, n -> fibonacci(n-1) + fibonacci(n-2));
    }

    public static void main(String[] args) {
        System.out.println(fibonacci(10));
        cache.forEach((key, value) -> {
            System.out.println(key + ": " + value);
        });
    }
}
相關文章
相關標籤/搜索