如何在java8項(xiàng)目中自定義collector

本篇文章給大家分享的是有關(guān)如何在java 8項(xiàng)目中自定義collector,小編覺得挺實(shí)用的,因此分享給大家學(xué)習(xí),希望大家閱讀完這篇文章后可以有所收獲,話不多說,跟著小編一起來看看吧。

創(chuàng)新互聯(lián)專注于邵武網(wǎng)站建設(shè)服務(wù)及定制,我們擁有豐富的企業(yè)做網(wǎng)站經(jīng)驗(yàn)。 熱誠為您提供邵武營銷型網(wǎng)站建設(shè),邵武網(wǎng)站制作、邵武網(wǎng)頁設(shè)計(jì)、邵武網(wǎng)站官網(wǎng)定制、小程序開發(fā)服務(wù),打造邵武網(wǎng)絡(luò)公司原創(chuàng)品牌,更為您提供邵武網(wǎng)站排名全網(wǎng)營銷落地服務(wù)。

需求:

將 一個(gè)容器List<Bean> 按照一定的字段進(jìn)行分組,分組過后的值為特定的BEAN 里面的屬性例如:

假定有這樣一個(gè)Bean

 public class SubjectOberser{
  private String subjectKey;
  private AbstractObserver abstractObserver;
  ...geter seter 方法...
 } 

我們需要按照 subjectKey 進(jìn)行分組,分組過后的內(nèi)容 應(yīng)該為這樣一個(gè)容器Map<String,List<AbstractObserver>>

map 中的key,為SubjectOberser 屬性的subjectKey,值為List<AbstractObserver>

實(shí)現(xiàn)過程

首先來看看collector 的接口定義

 public interface Collector<T, A, R> { 
   Supplier<A> supplier();
   BiConsumer<A, T> accumulator();
   Function<A, R> finisher();
   BinaryOperator<A> combiner();
   Set<Characteristics> characteristics();
 }

類型 T ,是在容器里面元素的類型

類型 A ,是accumulator 返回的類型,即是累加器的返回類型

類型 R ,是最終結(jié)果的類型

supplier 方法返回的結(jié)果必須為一個(gè)空的Supplier,也就是一個(gè)空的無參函數(shù)(簽名就是這樣的 ()->{}),在調(diào)用的時(shí)候它會(huì)創(chuàng)建一個(gè)空的累加器(accumulator)實(shí)例,供數(shù)據(jù)收集的時(shí)候使用,很明顯如果按照我們的需求試下你自己collector 這里應(yīng)該返回一個(gè) () -> new HashMap<>() ,一個(gè)Map 來收集結(jié)果

accumulator 方法返回歸約操作的函數(shù)(簽名是這樣的 (a,b)->void ),當(dāng)遍歷到流中第n個(gè)元素時(shí),這個(gè)函數(shù)執(zhí)行時(shí)會(huì)有兩個(gè)參數(shù):保存歸約結(jié)果的累加器(已 收集了流中的前n-1個(gè)項(xiàng)目),還有第n個(gè)元素本身。簽名也展示該函數(shù)是void,因?yàn)樵摬僮魇窃谠瓉淼娜萜骼锩孢M(jìn)行更新的,所以返回的是void 類型。按照需求的中的實(shí)現(xiàn)應(yīng)該是是這樣的:

 public BiConsumer<Map<String, List<AbstractObserver>>, SubjectObserver> accumulator() {
  return (Map<String, List<AbstractObserver>> acc, SubjectObserver v) -> {
   if (acc.containsKey(v.getSubjectKey())){
    acc.get(v.getSubjectKey()).add(v.getAbstractObserver());
   }else{
    List<AbstractObserver> l = new ArrayList<>();
    l.add(v.getAbstractObserver());
    acc.put(v.getSubjectKey(),l);
   }
  };
 }

這里的邏輯就是if else  邏輯判斷就是,這個(gè)key ,在map 中是否存在,如果不存在,那么我們需要給他new一個(gè)list 的實(shí)例,不然我的的數(shù)據(jù)沒有地方存儲(chǔ)

finisher 可從名字看出方法累積過程的最后要調(diào)用的一個(gè)函數(shù),以便將累加器對象轉(zhuǎn)換為整個(gè)集合操作的最終結(jié)果。通常來說累加器的類型也是返回的結(jié)果的類型,那么就返回identity 就可以了,如果不是的話,就行自行轉(zhuǎn)換了。在當(dāng)前需求的情況下我們的累加器和返回結(jié)果的類型是一致的,所以這里的實(shí)現(xiàn)是這樣的:

 public Function<Map<String, List<AbstractObserver>>,
     Map<String, List<AbstractObserver>>> finisher(){
   return Function.identity();
 }

combiner 方法是將兩個(gè)累加的結(jié)果進(jìn)行一個(gè)合并的過程,當(dāng)然這個(gè)過程并不是每一個(gè)collector 都會(huì)調(diào)用得到(后面會(huì)講到)
按照我們的需求,只需要將兩個(gè)累加器的,中間結(jié)果合并成為一個(gè)結(jié)果即可,所以是現(xiàn)實(shí)這樣的:

  public BinaryOperator<Map<String, List<AbstractObserver>>> combiner() {
  return ((Map<String, List<AbstractObserver>> map1, 
    Map<String, List<AbstractObserver>> map2) -> {
     map1.putAll(map2);
     return map1;
   });
 }

characteristics 該方法返回一個(gè) Characteristics 的集合,它有如下值可選

    UNORDERED—— 歸約結(jié)果不受流中項(xiàng)目的遍歷和累積順序的影響。

    CONCURRENT—— accumulator函數(shù)可以從多個(gè)線程同時(shí)調(diào)用,且該收集器可以并行執(zhí)行。如果收集器沒有標(biāo)為UNORDERED,那 它僅在用于用于無序數(shù)據(jù)源時(shí)才可以并行歸約。

    IDENTITY_ FINISH—— 這表明完成器方法返回的函數(shù)是一個(gè)不改變的函數(shù),這種情況下,累加器對象將會(huì)直接用作合并過程 的最終結(jié)果。

   public Set<Characteristics> characteristics() {
    return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
   }

最終collector 代碼合在一起就是:

 public class MyCollector implements Collector<SubjectObserver,
  Map<String, List<AbstractObserver>>,
  Map<String, List<AbstractObserver>>> {


  @Override
  public Supplier<Map<String, List<AbstractObserver>>> supplier() {
   return () -> new HashMap<>();
  }

  @Override
  public BiConsumer<Map<String, List<AbstractObserver>>, SubjectObserver> accumulator() {
   return (Map<String, List<AbstractObserver>> acc, SubjectObserver v) -> {
    if (acc.containsKey(v.getSubjectKey())) {
     acc.get(v.getSubjectKey()).add(v.getAbstractObserver());
    } else {
     List<AbstractObserver> l = new ArrayList<>();
     l.add(v.getAbstractObserver());
     acc.put(v.getSubjectKey(), l);
    }
   };
  }

  @Override
  public BinaryOperator<Map<String, List<AbstractObserver>>> combiner() {
   return ((Map<String, List<AbstractObserver>> map1, Map<String, List<AbstractObserver>> map2) -> {
    map1.putAll(map2);
    return map1;
   });
  }

  @Override
  public Function<Map<String, List<AbstractObserver>>, Map<String, List<AbstractObserver>>> finisher() {
   return Function.identity();
  }

  @Override
  public Set<Characteristics> characteristics() {
   return Collections.unmodifiableSet(EnumSet.of(Characteristics.IDENTITY_FINISH));
  }
 }

調(diào)用的過程就是:

 public static Map<String, List<AbstractObserver>> initObjectMap() {
 ClassScaner classScaner = new ClassScaner();
 Set<Class> set = classScaner.doScan("com.souche.datacenter.observer");
 return set
   .stream()
   .filter(aClass -> SubjectAnnotationResolver.getAnnotationSubjectName(aClass) != null)
   .map(aClass -> {
    String subjectKey = SubjectAnnotationResolver.getAnnotationSubjectName(aClass);
    AbstractObserver abstractObserver = getBeanByClassName(aClass.getSimpleName());
    return new SubjectObserver(subjectKey, abstractObserver);
   }).collect(new MyCollector());
 }

直接在使用的地方直接new MyCollector 就可以了

以上就是如何在java 8項(xiàng)目中自定義collector,小編相信有部分知識點(diǎn)可能是我們?nèi)粘9ぷ鲿?huì)見到或用到的。希望你能通過這篇文章學(xué)到更多知識。更多詳情敬請關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道。

網(wǎng)頁題目:如何在java8項(xiàng)目中自定義collector
本文來源:http://muchs.cn/article46/geddeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站改版、自適應(yīng)網(wǎng)站、外貿(mào)網(wǎng)站建設(shè)企業(yè)建站、靜態(tài)網(wǎng)站、營銷型網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

h5響應(yīng)式網(wǎng)站建設(shè)