偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

Java12 Collectors.teeing你真的需要了解一下

開發(fā) 后端
在 Java 12 里面有個(gè)非常好用但在官方 JEP 沒有公布的功能,因?yàn)樗皇?Collector 中的一個(gè)小改動(dòng),它的作用是 merge 兩個(gè) collector 的結(jié)果。

前言

在 Java 12 里面有個(gè)非常好用但在官方 JEP 沒有公布的功能,因?yàn)樗皇?Collector 中的一個(gè)小改動(dòng),它的作用是 merge 兩個(gè) collector 的結(jié)果,這句話顯得很抽象,老規(guī)矩,我們先來看個(gè)圖:

管道改造經(jīng)常會(huì)用這個(gè)小東西,通常我們叫它「三通」,它的主要作用就是將 downstream1 和 downstream2 的流入合并,然后從 merger 流出

有了這個(gè)形象的說明我們就進(jìn)入正題吧

Collectors.teeing

上面提到的小功能就是 Collectors.teeing API, 先來看一下 JDK 關(guān)于該 API 的說明,看著覺得難受的直接忽略,繼續(xù)向下看例子就好了: 

  1. /**  
  2.  * Returns a {@code Collector} that is a composite of two downstream collectors.  
  3.  * Every element passed to the resulting collector is processed by both downstream  
  4.  * collectors, then their results are merged using the specified merge function  
  5.  * into the final result.  
  6.  *  
  7.  * <p>The resulting collector functions do the following:  
  8.  *  
  9.  * <ul>  
  10.  * <li>supplier: creates a result container that contains result containers  
  11.  * obtained by calling each collector's supplier  
  12.  * <li>accumulator: calls each collector's accumulator with its result container  
  13.  * and the input element  
  14.  * <li>combiner: calls each collector's combiner with two result containers  
  15.  * <li>finisher: calls each collector's finisher with its result container,  
  16.  * then calls the supplied merger and returns its result.  
  17.  * </ul>  
  18.  *  
  19.  * <p>The resulting collector is {@link Collector.Characteristics#UNORDERED} if both downstream  
  20.  * collectors are unordered and {@link Collector.Characteristics#CONCURRENT} if both downstream  
  21.  * collectors are concurrent.  
  22.  *  
  23.  * @param <T>         the type of the input elements  
  24.  * @param <R1>        the result type of the first collector  
  25.  * @param <R2>        the result type of the second collector  
  26.  * @param <R>         the final result type  
  27.  * @param downstream1 the first downstream collector  
  28.  * @param downstream2 the second downstream collector  
  29.  * @param merger      the function which merges two results into the single one  
  30.  * @return a {@code Collector} which aggregates the results of two supplied collectors.  
  31.  * @since 12  
  32.  */  
  33. public static <T, R1, R2, R>  
  34. Collector<T, ?, R> teeing(Collector<? super T, ?, R1> downstream1,  
  35.                           Collector<? super T, ?, R2> downstream2,  
  36.                           BiFunction<? super R1, ? super R2, R> merger) {  
  37.     return teeing0(downstream1, downstream2, merger);  

API 描述重的一句話非常關(guān)鍵: 

Every element passed to the resulting collector is processed by both downstream collectors

結(jié)合「三通圖」來說明就是,集合中每一個(gè)要被傳入 merger 的元素都會(huì)經(jīng)過 downstream1 和 downstream2 的加工處理

其中 merger 類型是 BiFunction,也就是說接收兩個(gè)參數(shù),并輸出一個(gè)值,請(qǐng)看它的 apply 方法 

  1. @FunctionalInterface  
  2. public interface BiFunction<T, U, R> {  
  3.     /**  
  4.      * Applies this function to the given arguments.  
  5.      *  
  6.      * @param t the first function argument  
  7.      * @param u the second function argument  
  8.      * @return the function result  
  9.      */  
  10.     R apply(T t, U u);  

至于可以如何處理,我們來看一些例子吧

例子

為了更好的說明 teeing 的使用,列舉了四個(gè)例子,看過這四個(gè)例子再回看上面的 API 說明,相信你會(huì)柳暗花明了

計(jì)數(shù)和累加

先來看一個(gè)經(jīng)典的問題,給定的數(shù)字集合,需要映射整數(shù)流中的元素?cái)?shù)量和它們的和 

  1. class CountSum {  
  2.     private final Long count;  
  3.     private final Integer sum;  
  4.     public CountSum(Long count, Integer sum) {  
  5.         this.count = count; 
  6.          this.sum = sum;  
  7.     }  
  8.     @Override  
  9.     public String toString() {  
  10.         return "CountSum{" +  
  11.                 "count=" + count +  
  12.                 ", sum=" + sum +  
  13.                 '}';  
  14.     }  

通過 Collectors.teeing 處理 

  1. CountSum countsum = Stream.of(2, 11, 1, 5, 7, 8, 12)  
  2.         .collect(Collectors.teeing(  
  3.                 counting(),  
  4.                 summingInt(e -> e),  
  5.                 CountSum::new));  
  6. System.out.println(countsum.toString()); 
  •  downstream1 通過 Collectors 的靜態(tài)方法 counting 進(jìn)行集合計(jì)數(shù)
  •  downstream2 通過 Collectors 的靜態(tài)方法 summingInt 進(jìn)行集合元素值的累加
  •  merger 通過 CountSum 構(gòu)造器收集結(jié)果

運(yùn)行結(jié)果: 

  1. CountSum{count=7sum=46

我們通過 teeing 一次性得到我們想要的結(jié)果,繼續(xù)向下看其他例子:

最大值與最小值

通過給定的集合, 一次性計(jì)算出集合的最大值與最小值,同樣新建一個(gè)類 MinMax,并創(chuàng)建構(gòu)造器用于 merger 收集結(jié)果 

  1. class MinMax {  
  2.     private final Integer min;  
  3.     private final Integer max;  
  4.     public MinMax(Integer min, Integer max) {  
  5.         this.min = min;  
  6.         this.max = max;  
  7.     }  
  8.     @Override  
  9.     public String toString() {  
  10.         return "MinMax{" +  
  11.                 "min=" + min +  
  12.                 ", max=" + max +  
  13.                 '}';  
  14.     }  

通過 teeing API 計(jì)算結(jié)果: 

  1. MinMax minmax = Stream.of(2, 11, 1, 5, 7, 8, 12)  
  2.         .collect(Collectors.teeing(  
  3.                 minBy(Comparator.naturalOrder()),  
  4.                 maxBy(Comparator.naturalOrder()),  
  5.                 (Optional<Integer> a, Optional<Integer> b) -> new MinMax(a.orElse(Integer.MIN_VALUE), b.orElse(Integer.MAX_VALUE))));  
  6. System.out.println(minmax.toString()); 
  •  downstream1 通過 Collectors 的靜態(tài)方法 minBy,通過 Comparator 比較器按照自然排序找到最小值
  •  downstream2 通過 Collectors 的靜態(tài)方法 maxBy,通過 Comparator 比較器按照自然排序找到最大值
  •  merger 通過 MinMax 構(gòu)造器收集結(jié)果,只不過為了應(yīng)對(duì) NPE,將 BiFunction 的兩個(gè)入?yún)⒔?jīng)過 Optional 處理

運(yùn)行結(jié)果:   

  1. MinMax{min=1max=12

為了驗(yàn)證一下 Optional,我們將集合中添加一個(gè) null 元素,并修改一下排序規(guī)則來看一下排序結(jié)果: 

  1. MinMax minmax = Stream.of(null, 2, 11, 1, 5, 7, 8, 12)  
  2.                 .collect(Collectors.teeing(  
  3.                         minBy(Comparator.nullsFirst(Comparator.naturalOrder())),  
  4.                         maxBy(Comparator.nullsLast(Comparator.naturalOrder())),  
  5.                         (Optional<Integer> a, Optional<Integer> b) -> new MinMax(a.orElse(Integer.MIN_VALUE), b.orElse(Integer.MAX_VALUE)))); 
  •  downstream1 處理規(guī)則是將 null 放在排序的最前面
  •  downstream2 處理規(guī)則是將 null 放在排序的最后面
  •  merger 處理時(shí),都會(huì)執(zhí)行 optional.orElse 方法,分別輸出最小值與最大值

運(yùn)行結(jié)果:   

  1. MinMax{min=-2147483648, max=2147483647

瓜的總重和單個(gè)重量

接下來舉一個(gè)更貼合實(shí)際的操作對(duì)象的例子 

  1. // 定義瓜的類型和重量  
  2. class Melon {  
  3.     private final String type;  
  4.     private final int weight;  
  5.     public Melon(String type, int weight) {  
  6.         this.type = type;  
  7.         this.weight = weight;  
  8.     }  
  9.     public String getType() {  
  10.         return type;  
  11.     }  
  12.     public int getWeight() {  
  13.         return weight;  
  14.     }  
  15.  
  16. // 總重和單個(gè)重量列表  
  17. class WeightsAndTotal {  
  18.     private final int totalWeight;  
  19.     private final List<Integer> weights;  
  20.     public WeightsAndTotal(int totalWeight, List<Integer> weights) {  
  21.         this.totalWeight = totalWeight;  
  22.         this.weights = weights;  
  23.     }  
  24.     @Override  
  25.     public String toString() {  
  26.         return "WeightsAndTotal{" +  
  27.                 "totalWeight=" + totalWeight +  
  28.                 ", weights=" + weights +  
  29.                 '}';  
  30.     }  

通過 teeing API 計(jì)算總重量和單個(gè)列表重量 

  1. List<Melon> melons = Arrays.asList(new Melon("Crenshaw", 1200),  
  2.     new Melon("Gac", 3000), new Melon("Hemi", 2600),  
  3.     new Melon("Hemi", 1600), new Melon("Gac", 1200),  
  4.     new Melon("Apollo", 2600), new Melon("Horned", 1700),  
  5.     new Melon("Gac", 3000), new Melon("Hemi", 2600)  
  6. );  
  7. WeightsAndTotal weightsAndTotal = melons.stream()  
  8.     .collect(Collectors.teeing(  
  9.             summingInt(Melon::getWeight),  
  10.             mapping(m -> m.getWeight(), toList()),  
  11.             WeightsAndTotal::new));  
  12. System.out.println(weightsAndTotal.toString()); 
  •  downstream1 通過 Collectors 的靜態(tài)方法 summingInt 做重量累加
  •  downstream2 通過 Collectors 的靜態(tài)方法 mapping 提取出瓜的重量,并通過流的終結(jié)操作 toList() 獲取結(jié)果
  •  merger 通過 WeightsAndTotal 構(gòu)造器獲取結(jié)果

運(yùn)行結(jié)果:   

  1. WeightsAndTotal{totalWeight=19500weights=[1200, 3000, 2600, 1600, 1200, 2600, 1700, 3000, 2600]} 

繼續(xù)一個(gè)更貼合實(shí)際的例子吧:

預(yù)約人員列表和預(yù)約人數(shù) 

  1. class Guest {  
  2.     private String name;  
  3.     private boolean participating;  
  4.     private Integer participantsNumber;  
  5.     public Guest(String name, boolean participating, Integer participantsNumber) {  
  6.         this.name = name;  
  7.         this.participating = participating;  
  8.         this.participantsNumber = participantsNumber;  
  9.     }  
  10.     public boolean isParticipating() {  
  11.         return participating;  
  12.     }  
  13.     public Integer getParticipantsNumber() {  
  14.         return participantsNumber;  
  15.     }  
  16.     public String getName() {  
  17.         return name;  
  18.     }  
  19.  
  20. class EventParticipation {  
  21.     private List<String> guestNameList;  
  22.     private Integer totalNumberOfParticipants;  
  23.     public EventParticipation(List<String> guestNameList, Integer totalNumberOfParticipants) {  
  24.         this.guestNameList = guestNameList;  
  25.         this.totalNumberOfParticipants = totalNumberOfParticipants; 
  26.     }  
  27.     @Override  
  28.     public String toString() {  
  29.         return "EventParticipation { " +  
  30.                 "guests = " + guestNameList +  
  31.                 ", total number of participants = " + totalNumberOfParticipants +  
  32.                 " }";  
  33.     }  

通過 teeing API 處理 

  1. var result = Stream.of(  
  2.                 new Guest("Marco", true, 3),  
  3.                 new Guest("David", false, 2),  
  4.                 new Guest("Roger",true, 6))  
  5.                 .collect(Collectors.teeing(  
  6.                         Collectors.filtering(Guest::isParticipating, Collectors.mapping(Guest::getName, Collectors.toList())),  
  7.                         Collectors.summingInt(Guest::getParticipantsNumber),  
  8.                         EventParticipation::new  
  9.                 ));  
  10. System.out.println(result); 
  •  downstream1 通過 filtering 方法過濾出確定參加的人,并 mapping 出他們的姓名,最終放到 toList 集合中
  •  downstream2 通過 summingInt 方法計(jì)數(shù)累加
  •  merger 通過 EventParticipation 構(gòu)造器收集結(jié)果

其中我們定義了 var result 來收集結(jié)果,并沒有指定類型,這個(gè)語法糖也加速了我們編程的效率

運(yùn)行結(jié)果:   

  1. EventParticipation { guests = [Marco, Roger], total number of participants = 11 } 

總結(jié)

其實(shí) teeing API 就是靈活應(yīng)用 Collectors 里面定義的靜態(tài)方法,將集合元素通過 downstream1 和 downstream2 進(jìn)行處理,最終通過 merger 收集起來,當(dāng)項(xiàng)目中有同時(shí)獲取兩個(gè)收集結(jié)果時(shí),是時(shí)候應(yīng)用我們的 teeing API 了。 

 

責(zé)任編輯:龐桂玉 來源: segmentfault
相關(guān)推薦

2015-12-23 10:00:04

多種編程語言

2021-07-06 14:56:20

深度學(xué)習(xí)編程人工智能

2021-05-19 09:40:14

Android 12Android

2024-01-31 13:02:00

高并發(fā)熱點(diǎn)散列庫存分桶

2012-06-26 10:13:55

2011-04-01 11:16:06

hessian

2012-06-27 09:11:47

2022-08-25 14:42:45

JavaScrip字符串

2021-08-09 14:40:02

物聯(lián)網(wǎng)IOT智能家居

2017-09-22 14:12:33

Android字體 Typeface

2017-11-16 18:48:48

Hadoop數(shù)據(jù)庫數(shù)據(jù)處理

2018-04-02 14:21:43

互聯(lián)網(wǎng)物聯(lián)網(wǎng)

2016-11-01 16:41:08

直通網(wǎng)線連接端口傳輸數(shù)據(jù)

2023-05-28 18:21:32

2022-01-04 19:28:05

VMware云端虛擬化

2020-10-13 06:56:19

JavaScript異常類型開發(fā)

2022-10-26 07:21:15

網(wǎng)絡(luò)視頻開發(fā)

2010-04-30 10:05:31

企業(yè)級(jí)Linux

2015-09-17 09:36:46

Chrome改變

2022-07-29 09:17:46

JavaScriptReactJS學(xué)習(xí)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)