收集器

一种通用的、从流生成复杂值的结构,只要把它传给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);
        });
    }
}
相关文章
相关标签/搜索