一種通用的、從流生成複雜值的結構,只要把它傳給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); }); } }