国产xxxx99真实实拍_久久不雅视频_高清韩国a级特黄毛片_嗯老师别我我受不了了小说

資訊專欄INFORMATION COLUMN

Java8 collector接口的定制實現

zhangwang / 3387人閱讀

摘要:寫這個文章其實主要是因為剛有個童鞋問了個問題正寫的帶勁安利的實現方式,結果還沒寫完無意發現問題被關閉了哎都寫了一半了又不想放棄,就干脆寫成文章問題主要就是把集合里的數據按照一定大小順序平均分成若干組的問題,看起來挺簡單的,不過我開始看到就想

寫這個文章其實主要是因為剛有個童鞋問了個問題https://segmentfault.com/q/10...
正寫的帶勁安利Java8的實現方式,結果還沒寫完...無意發現問題被關閉了...哎...都寫了一半了...又不想放棄,就干脆寫成文章

問題主要就是把集合里的數據按照一定大小順序平均分成若干組的問題,看起來挺簡單的,不過我開始看到就想用用stream來實現,但是想了想Collectors里并沒有適合的方法,所以就想到了用定制的collector來實現了。
原問題的截圖:

正式開始回答(我是直接把之前的回答copy過來的哈):

集合處理的話,我還是推薦Java8stream,題主這個問題設計到分組,那自然就要涉及到streamcollect方法了,這個方法是收集數據的意思,該方法的參數就是一個Collector接口,只要傳入一個Collector的實現類就可以了,常用的實現比如在工具類Collectors里有toList,toMap等,已經幫你默認寫了收集為集合或者Map的實現類了,但是明顯這些實現類都不合適,所以這里需要定制一個Collector接口的實現啦

其實就是仿照Collectors里的內部類CollectorImpl寫一個就是了...

=====================(Collector介紹,如果你已經清楚可以略過的...)==================

介紹哈Collector接口的方法,一共5個

Supplier supplier()
BiConsumer accumulator()
BinaryOperator combiner()
Function finisher()
Set characteristics()

方法中有泛型,所以要先要介紹哈Collector中的三個泛型T, A, R
Tstream在調用collect方法收集前的數據類型
AAT的累加器,遍歷T的時候,會把T按照一定的方式添加到A中,換句話說就是把一些T通過一種方式變成A
RR可以看成是A的累加器,是最終的結果,是把A匯聚之后的數據類型,換句話說就是把一些A通過一種方式變成R

了解了泛型的意思,咱們結合Collectors.toList構造的默認實現類的實現方式來看看Collector接口的方法

public static 
    Collector> toList() {
        return new CollectorImpl<>((Supplier>) ArrayList::new, List::add,
                                   (left, right) -> { left.addAll(right); return left; },
                                   CH_ID);
    }

官方寫的很簡單,很隨意...

前三個參數分別對應了Collector的前三個方法,也就是

(Supplier>) ArrayList::new 對應Supplier supplier()第一個方法
List::add 對應BiConsumer accumulator()第二個方法
(left, right) -> { left.addAll(right); return left; }對應BinaryOperator
combiner()第三個方法

所以對應著來看就清楚了
Supplier
supplier() 怎么創建一個累加器(這里對應的是如何創建一個List
BiConsumer accumulator()怎么把一個對象添加到累加器中(這里對應的是如何在List里添加一個對象,當然是調用add方法咯)
BinaryOperator
combiner()怎么把一個累加器和另一個累加器合并起來(這里對應的是如何把ListList合并起來,當然是調用addAll,這里由于最終要返回List,所以A和R是一個類型,都是List所以才調用addAll

再來看看第四個方法Function finisher(),其實就是怎么把A轉化為R,由于是toList,所以AR是一樣的類型,這里其實用就是Function.identity
最后第五個方法Set characteristics()其實就是這個Collector的一些性質,toList這里只用了Characteristics.IDENTITY_FINISH,表示第四個方法可以不用設置,A類型就是最終的結果

=====================(Collector介紹完了)==================

現在創建自定義的collector,類名我就叫NumberCollectorImpl,由于collector這里要求有三個泛型,根據題主的需求,這三個泛型只有第一個是未知的,另外兩個應該是確認的List結構,所以寫出來應該是這么個效果

static class NumberCollectorImpl implements Collector>, List>>

ok,針對collector要求實現的5個方法來依次說明
第一個方法Supplier>> supplier(),很明顯應該就是ArrayList::new
第二個方法BiConsumer>, T>,這個稍微麻煩點,起始應該寫成(list, item) -> {},主要就是補充{}中的代碼了
最開始的遍歷的時候,這個list其實是父list,它肯定是空的,所以這個時候要創建一個新子List,然后把item塞進子list中,最后再把創建的新子list放入到父list

if (list.isEmpty()){
  list.add(this.createNewList(item));
}

這里簡單封了一個小方法createNewList,因為待會還要用

private List createNewList(T item){
   List newOne = new ArrayList();
   newOne.add(item);
   return newOne;
}

若父list不為空,那就要把當前父list中最后一個子list取出來,若空的話,當然又是要創建一個新子list然后按照之前的方法做,若不為空,就判斷子list大小咯,若大小超過2,就再次創建一個新子list然后塞item,若沒有超過就在之前子list中塞入item,寫出來大概就是這個樣子

List last = (List) list.get(list.size() - 1);
if (last.size() < 2){
    last.add(item);
}else{
    list.add(this.createNewList(item));
}

第三個方法BinaryOperator>> combiner(),其實就是兩個List如何合并,當然是addAll方法

(list1, list2) -> {
   list1.addAll(list2);
   return list1;
};

第四個方法Function>, List>> finisher(),由于這個時候A和R的類型一樣,都是List>,所以這里直接就是Function.identity()

最后一個方法Set characteristics()這里直接可以按照Collectors.toList來弄就行了,也就是直接采用Collections.unmodifiableSet(EnumSet.of(Collector.Characteristics.IDENTITY_FINISH))

綜上所述,完整代碼如下

/**
 * 自定義Collector
 *
 * @author imango
 * @since 2017/7/13
 */
public class CustomCollectors {

    // 默認采用2個一起分組
    public static  Collector>, List>> groupByNumber(){
        return CustomCollectors.groupByNumber(2);
    }
    
    // 根據number的大小進行分組
    public static  Collector>, List>> groupByNumber(int number){
        return new NumberCollectorImpl(number);
    }

    /**
     * 個數分組器
     * @param 
     */
    static class NumberCollectorImpl implements Collector>, List>> {
        // 每組的個數
        private int number;

        public NumberCollectorImpl(int number) {
            this.number = number;
        }

        @Override
        public Supplier>> supplier() {
            return ArrayList::new;
        }

        @Override
        public BiConsumer>, T> accumulator() {
            return (list, item) -> {
                if (list.isEmpty()){
                    list.add(this.createNewList(item));
                }else {
                    List last = (List) list.get(list.size() - 1);
                    if (last.size() < number){
                        last.add(item);
                    }else{
                        list.add(this.createNewList(item));
                    }
                }
            };
        }

        @Override
        public BinaryOperator>> combiner() {
            return (list1, list2) -> {
                list1.addAll(list2);
                return list1;
            };
        }

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

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

        private List createNewList(T item){
            List newOne = new ArrayList();
            newOne.add(item);
            return newOne;
        }
    }
}

外面那個類CustomCollectors 主要是為了封裝NumberCollectorImpl類,以后也可以把其他自定義的收集器實現放在這里面,并對外提供工具方法,并且我在NumberCollectorImpl類中新增了一個number成員變量,這樣就可以自定義分組大小了,CustomCollectors提供了兩個對外方法groupByNumber,帶參數的那個就是可以自定義分組個數的了,沒有參數的就是默認按照2個分組了,這樣的話,測試寫法就是這樣

public static void main(String[] args) {
   List list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
   // 按照2個分組
   List> twoNumberList = list.stream().collect(CustomCollectors.groupByNumber());
   // 按照5個分組
   List> fiveNumberList = list.stream().collect(CustomCollectors.groupByNumber(5));
}

這樣代碼就非常漂亮了~哈哈哈~~

文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。

轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/71143.html

相關文章

  • 樂字節-Java8新特性之Stream流(下)

    摘要:歸約操作計算有效訂單總金額有效訂單總金額收集數據收集將流轉換為其他形式,方法作為終端操作,接收一個接口的實現,用于給中元素做匯總的方法。 接上一篇:《Java8新特性之stream》,下面繼續接著講Stream 5、流的中間操作 常見的流的中間操作,歸為以下三大類:篩選和切片流操作、元素映射操作、元素排序操作:showImg(https://segmentfault.com/img/b...

    20171112 評論0 收藏0
  • Java8中創建Stream 流四種方式以及 Stream 中間操作

    摘要:一創建里流的四種方式第一種通過得方法串行流或者方法并行流創建。終止操作時一次性全部處理,稱為延遲加載篩選切片過濾中建操作。終止操作只有執行終止操作才會執行全部。即延遲加載結果中建操作。截斷流,使其元素不超過給定數量。返回流中最大值。 Stream api **Stream api 是java8 中提供的對集合處理的api , 對數據進行一系列的中間操作,元數據不會發生改變 ...

    0xE7A38A 評論0 收藏0
  • Java8流特性和Lambda表達式

    摘要:表達式體現了函數式編程的思想,即一個函數亦可以作為另一個函數參數和返回值,使用了函數作參數返回值的函數被稱為高階函數。對流對象進行及早求值,返回值不在是一個對象。 Java8主要的改變是為集合框架增加了流的概念,提高了集合的抽象層次。相比于舊有框架直接操作數據的內部處理方式,流+高階函數的外部處理方式對數據封裝更好。同時流的概念使得對并發編程支持更強。 在語法上Java8提供了Lamb...

    gaara 評論0 收藏0
  • Stream流與Lambda表達式(二) Stream收集器 Collector接口

    摘要:一收集器接口陳楊收集器接口匯聚操作的元素類型即流中元素類型匯聚操作的可變累積類型匯聚操作的結果類型接口一種可變匯聚操作將輸入元素累積到可變結果容器中在處理完所有輸入元素后可以選擇將累積的結果轉換為最終表示可選操作歸約操作 一、Stream收集器 Collector接口 package com.java.design.java8.Stream; import com.java.desi...

    or0fun 評論0 收藏0
  • 樂字節-Java8核心特性實戰之Stream(流)

    摘要:大家好,我是樂字節的小樂。需要注意的是很多流操作本身就會返回一個流,所以多個操作可以直接連接起來,如下圖這樣,操作可以進行鏈式調用,并且并行流還可以實現數據流并行處理操作。為集合創建并行流。 大家好,我是樂字節的小樂。說起流,我們會聯想到手機、電腦組裝流水線,物流倉庫商品包裝流水線等等,如果把手機 ,電腦,包裹看做最終結果的話,那么加工商品前的各種零部件就可以看做數據源,而中間一系列的...

    wenshi11019 評論0 收藏0

發表評論

0條評論

zhangwang

|高級講師

TA的文章

閱讀更多
最新活動
閱讀需要支付1元查看
<