JDK1.8新特性(二):Collectors收集器類


一. 什么是Collectors?

Java 8 API添加了一個新的抽象稱為流Stream,我們借助Stream API可以很方便的操作流對象。

Stream中有兩個方法collect和collectingAndThen,可以借助Collectors收集器類對流中的數據進行聚合操作,例如將元素累積到集合中,並根據各種標准對元素進行匯總,分類等操作。

二. 舉個例子?

//獲取String集合
List<String> strings = Arrays.asList("ab", "", "bc", "cd", "abcd","", "jkl");
//通過stream操作集合
List<String> stringList = strings.stream()
    //為集合中的每一個元素拼接“???”
    .map(s -> s += "???")
    //返回集合
    .collect(Collectors.toList());

如代碼所示,我們可以很方便的通過Collectors類對被處理的流數據進行聚合操作,包括並不僅限與將處理過的流轉換成集合

三. 如何使用Collectors?

1. Collectors類中提供的方法

總結一下,就是以下幾類方法:

1.1 轉換成集合:toList(),toSet(),toMap(),toCollection()

1.2 將集合拆分拼接成字符串:joining()

1.3 求最大值、最小值、求和、平均值 :maxBy(),minBy(),summingInt(),averagingDouble()

1.4 對集合分組:groupingBy(),partitioningBy()

1.5 對數據進行映射:mapping()

2. Collectors類方法源碼

public final class Collectors {

    // 轉換成集合
    public static <T> Collector<T, ?, List<T>> toList();
    public static <T> Collector<T, ?, Set<T>> toSet();
    public static <T, K, U> Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                                            Function<? super T, ? extends U> valueMapper);
    public static <T, C extends Collection<T>> Collector<T, ?, C> toCollection(Supplier<C> collectionFactory);

    // 拼接字符串,有多個重載方法                                  
    public static Collector<CharSequence, ?, String> joining(CharSequence delimiter);   
    public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,
                                                             CharSequence prefix,
                                                             CharSequence suffix);      
    // 最大值、最小值、求和、平均值                                                         
    public static <T> Collector<T, ?, Optional<T>> maxBy(Comparator<? super T> comparator);
    public static <T> Collector<T, ?, Optional<T>> minBy(Comparator<? super T> comparator);
    public static <T> Collector<T, ?, Integer> summingInt(ToIntFunction<? super T> mapper);      
    public static <T> Collector<T, ?, Double> averagingDouble(ToDoubleFunction<? super T> mapper);                   

    // 分組:可以分成true和false兩組,也可以根據字段分成多組                                 
    public static <T, K> Collector<T, ?, Map<K, List<T>>> groupingBy(Function<? super T, ? extends K> classifier);
    // 只能分成true和false兩組
    public static <T> Collector<T, ?, Map<Boolean, List<T>>> partitioningBy(Predicate<? super T> predicate);

    // 映射
    public static <T, U, A, R> Collector<T, ?, R> mapping(Function<? super T, ? extends U> mapper,
                                                          Collector<? super U, A, R> downstream);

    public static <T, U> Collector<T, ?, U> reducing(U identity,
                                                     Function<? super T, ? extends U> mapper,
                                                     BinaryOperator<U> op);
}

四. 實例

//接下來的示例代碼基於此集合
List<String> strings = Arrays.asList("ab", "s", "bc", "cd", "abcd","sd", "jkl");

1. 將流數據轉換成集合

//轉換成list集合
List<String> stringList = strings.stream().collect(Collectors.toList());

//轉換成Set集合
Set<String> stringSet = strings.stream().collect(Collectors.toSet());

//轉換成Map集合
Map<String,Object> stringObjectMap = strings.stream()
    .collect(Collectors.toMap(k -> k, v -> v ));

System.out.println(stringList);
System.out.println(stringSet);
System.out.println(stringObjectMap);

//=================打印結果=================
[ab, s, bc, cd, abcd, sd, jkl]
[ab, bc, cd, sd, s, jkl, abcd]
{sd=sd, cd=cd, bc=bc, ab=ab, s=s, jkl=jkl, abcd=abcd}

2. 將集合拆分拼接成字符串

//joining
String str1 = strings.stream()
    .collect(Collectors.joining("--"));

//collectingAndThen
String str2 = strings.stream()
    .collect(Collectors.collectingAndThen(
        //在第一個joining操作的結果基礎上再進行一次操作
        Collectors.joining("--"), s1 -> s1 += ",then"
    ));

System.out.println(str1);
System.out.println(str2);

//=================打印結果=================
ab--s--bc--cd--abcd--sd--jkl
ab--s--bc--cd--abcd--sd--jkl,then

3. 求最大值、最小值、求和、平均值

List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

//最大值
Integer maxValue = list.stream().collect(Collectors.collectingAndThen(
    //maxBy需要Comparator.comparingInt來確定排序規則
    Collectors.maxBy(Comparator.comparingInt(a -> a)), Optional::get
));
//最小值
Integer minValue = list.stream().collect(Collectors.collectingAndThen(
    //minBy需要Comparator.comparingInt來確定排序規則
    Collectors.minBy(Comparator.comparingInt(a -> a)), Optional::get
));
//求和
Integer sumValue = list.stream().collect(Collectors.summingInt(i -> i));
//平均值
Double avgValue = list.stream().collect(Collectors.averagingDouble(i -> i));

System.out.println("列表中最大的數 : " + maxValue);
System.out.println("列表中最小的數 : " + minValue);
System.out.println("所有數之和 : " + sumValue);
System.out.println("平均數 : " + avgValue);

//=================打印結果=================
列表中最大的數 : 5
列表中最小的數 : 1
所有數之和 : 15
平均數 : 3.0

雖然這樣也可以,但是明顯IntSummaryStatistics要更靈活點

4. 對集合分組

Map<Integer, List<String>> map = strings.stream()
    //根據字符串長度分組(同理,對對象可以通過某個屬性分組)
    .collect(Collectors.groupingBy(String::length));

Map<Boolean, List<String>> map2 = strings.stream()
    //根據字符串是否大於2分組
    .collect(Collectors.groupingBy(s -> s.length() > 2));

System.out.println(map);
System.out.println(map2);

//=================打印結果=================
{1=[s], 2=[ab, bc, cd, sd], 3=[jkl], 4=[abcd]}
{false=[ab, s, bc, cd, sd], true=[abcd, jkl]}

5.對數據進行映射

String str = strings.stream().collect(Collectors.mapping(
    //先對集合中的每一個元素進行映射操作
    s -> s += ",mapping",
    //再對映射的結果使用Collectors操作
    Collectors.collectingAndThen(Collectors.joining(";"), s -> s += "=====then" )
));

System.out.println(str);

//=================打印結果=================
ab,mapping;s,mapping;bc,mapping;cd,mapping;abcd,mapping;sd,mapping;jkl,mapping=====then


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM