《Java8函數語言程式設計》讀書筆記---收集器

J_W發表於2018-12-14

轉換成值

maxBy minBy averageInt等
例項程式碼:
Optional<Person> op=Stream.of(a,b).collect(maxBy(Comparator.comparing(p->p.id)));
複製程式碼

資料分塊

partitioningBy的原始碼:
public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate) {
    return partitioningBy(predicate, toList());
}
使用程式碼:
複製程式碼
 
public class Person {
    String name;
    String  id;

    public Person() {
    }

    public Person(String name, String id) {
        this.name = name;
        this.id = id;
    }

    @Override
    public String toString() {
        return name+id;
    }

    public static void main(String[] args) {
        Person a=new Person("tom","123");
        Person b=new Person("tomb","456");
        Person c=new Person("tomc","189");
        List list=Stream.of(a,b,c).flatMap(p->Stream.concat(Stream.of(p.id),Stream.of(p.name))).collect(toList());
        System.out.println(list);

        Optional<Person> op=Stream.of(a,b,c).collect(maxBy(Comparator.comparing(p->p.id)));
        System.out.println(op.get().name);

        Map<Boolean,List<Person>> map=Stream.of(a,b,c).collect(partitioningBy(p->p.id.startsWith("1")));
        System.out.println(map.get(true).toString());
        System.out.println(map.get(false));

    }
}
複製程式碼

資料分組 (groupingBy)

        Map<String, List<Person>> map1=Stream.of(a,b,c).collect(groupingBy(p->p.name));
        System.out.println(map1.get("tom"));
複製程式碼

Map中第一個泛型String,代表該groupingby是用一個String來分組的,該String為p.name 第二個泛型List《Person》,是得到的組。

組合成字串的方法 joining

String result=Stream.of(a,b,c).map(p->p.name).collect(Collectors.joining("-","[","]"));
複製程式碼

組合收集器

以上都是簡單的收集器,可以完成簡單的收集工作,但是一些較複雜的收集工作就需要組合收集器。
使用場景:
上述例子資料分組中,最終產生的是一個Map<String, List<Person>>,以name分組的Person列表{tom=[tom123, tom456], tomc=[tomc189]}。
如果我們想進一步統計,每個組,有多少個id該怎麼計算呢?
``` java
//groupingBy分組計數
    Map<String, Long> mapCounting=Stream.of(a,b,c).collect(groupingBy(p->p.name,counting()));
    System.out.println(mapCounting);
    
    執行結果:
    {tom=2, tomc=1}
```
複製程式碼

groupingBy 原始碼,下游收集器

/**
     * Returns a {@code Collector} implementing a cascaded "group by" operation
     * on input elements of type {@code T}, grouping elements according to a
     * classification function, and then performing a reduction operation on
     * the values associated with a given key using the specified downstream
     * {@code Collector}.
     *
     * <p>The classification function maps elements to some key type {@code K}.
     * The downstream collector operates on elements of type {@code T} and
     * produces a result of type {@code D}. The resulting collector produces a
     * {@code Map<K, D>}.
     *
     * <p>There are no guarantees on the type, mutability,
     * serializability, or thread-safety of the {@code Map} returned.
     *
     * <p>For example, to compute the set of last names of people in each city:
     * <pre>{@code
     *     Map<City, Set<String>> namesByCity
     *         = people.stream().collect(groupingBy(Person::getCity,
     *                                              mapping(Person::getLastName, toSet())));
     * }</pre>
     *
     * @implNote
     * The returned {@code Collector} is not concurrent.  For parallel stream
     * pipelines, the {@code combiner} function operates by merging the keys
     * from one map into another, which can be an expensive operation.  If
     * preservation of the order in which elements are presented to the downstream
     * collector is not required, using {@link #groupingByConcurrent(Function, Collector)}
     * may offer better parallel performance.
     *
     * @param <T> the type of the input elements
     * @param <K> the type of the keys
     * @param <A> the intermediate accumulation type of the downstream collector
     * @param <D> the result type of the downstream reduction
     * @param classifier a classifier function mapping input elements to keys
     * @param downstream a {@code Collector} implementing the downstream reduction
     * @return a {@code Collector} implementing the cascaded group-by operation
     * @see #groupingBy(Function)
     *
     * @see #groupingBy(Function, Supplier, Collector)
     * @see #groupingByConcurrent(Function, Collector)
     */
    public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
    }
複製程式碼
groupingBy的第二個引數叫做下游收集器(downstream),是最終結果的一個子集,counting(),mapping()等方法。
。
mapping下游收集器用法:生成一個Map<name,id>,
    //groupingBy mapping()
    Map<String,List<String>> mapMapping=Stream.of(a,b,c).collect(groupingBy(p->p.name,mapping(p->p.id,toList())));
    System.out.println(mapMapping);
複製程式碼

自定義收集器

//定製收集器
    StringCombiner combiner=Stream.of(a,b,c).map(p->p.name).reduce(new StringCombiner(",","[","]"),
                                            StringCombiner::add,
                                            StringCombiner::merge
                                            );
    System.out.println(combiner.toString());

    String selfCollector=Stream.of(a,b,c).map(p->p.name).collect(new StringCollector("-","[","]"));
複製程式碼

相關文章