日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程语言 > java >内容正文

java

Java 8系列之重构和定制收集器

發布時間:2025/3/21 java 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 8系列之重构和定制收集器 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Stream系列:

  • Java 8系列之Stream的基本語法詳解
  • Java 8系列之Stream的強大工具Collector
  • Java 8系列之重構和定制收集器
  • Java 8系列之Stream中萬能的reduce?

前面我們已經了解到了Collector類庫中各種收集器的強大,可是,它們也只是能滿足常用的場景。既然開放了Collector接口,我們當然可以根據自已意愿去定制,實際操作起來還是比較簡單的。

Collectors.joining源碼解析

從前面,我們已經了解到一個Collector是由四部分組成的:

  • Supplier<A> supplier(): 創建新的結果容器
  • BiConsumer<A, T> accumulator(): 將元素添加到結果容器
  • BinaryOperator<A> combiner(): 將兩個結果容器合并為一個結果容器
  • Function<A, R> finisher(): 對結果容器作相應的變換

我們先看Collectors.joining是怎么實現的:

String strJoin = Stream.of("1", "2", "3", "4").collect(Collectors.joining(",", "[", "]")); System.out.println("strJoin: " + strJoin); // 打印結果 // strJoin: [1,2,3,4]

這里,我們跟蹤代碼,看看Collectors.joining的源碼:

public static Collector<CharSequence, ?, String> joining(CharSequence delimiter,CharSequence prefix,CharSequence suffix) {return new CollectorImpl<>(() -> new StringJoiner(delimiter, prefix, suffix),StringJoiner::add, StringJoiner::merge,StringJoiner::toString, CH_NOID); }

Collectors.joining實際上返回的是一個CollectorImpl對象,而其是Collector接口的實現類。在創建CollectorImpl對象時,通過方法引用,將StringJoiner的add()、merge()、toString()方法分別傳遞給accumulator()、combiner()及finisher()等四部分。

static class CollectorImpl<T, A, R> implements Collector<T, A, R> {private final Supplier<A> supplier;private final BiConsumer<A, T> accumulator;private final BinaryOperator<A> combiner;private final Function<A, R> finisher;private final Set<Characteristics> characteristics;CollectorImpl(Supplier<A> supplier,BiConsumer<A, T> accumulator,BinaryOperator<A> combiner,Function<A,R> finisher,Set<Characteristics> characteristics) {this.supplier = supplier;this.accumulator = accumulator;this.combiner = combiner;this.finisher = finisher;this.characteristics = characteristics;}CollectorImpl(Supplier<A> supplier,BiConsumer<A, T> accumulator,BinaryOperator<A> combiner,Set<Characteristics> characteristics) {this(supplier, accumulator, combiner, castingIdentity(), characteristics);}@Overridepublic BiConsumer<A, T> accumulator() {return accumulator;}@Overridepublic Supplier<A> supplier() {return supplier;}@Overridepublic BinaryOperator<A> combiner() {return combiner;}@Overridepublic Function<A, R> finisher() {return finisher;}@Overridepublic Set<Characteristics> characteristics() {return characteristics;} }

首先要明確的是參數類型,

  • 待收集元素的類型:String;
  • 累加器的類型:StringCombiner;
  • 最終結果的類型:String。

然后,我們一邊閱讀代碼, 一邊看圖, 這樣就能看清Collector到底是怎么工作的。由于Collector可以并行收集,為了可以了解清楚Collector的四部分的作用,我們這里以Collector在兩個容器上并行執行。

Collector的每一個組件都是函數,因此我們使用箭頭表示,Stream中的值用圓圈表示,最終生成的值用橢圓表示。Collector一開始的工作就是創建一個容器。這里我們是實現了Supplier,這是一個工廠方法。

public Supplier<StringJoiner> supplier() {return () -> new StringJoiner(delim, prefix, suffix); }


Collector的accumulator函數的作用就是,它結合之前操作的結果和當前值,生成并返回新的值。 這一邏輯是通過StringJoiner::add方法實現的。

public StringJoiner add(CharSequence newElement) {prepareBuilder().append(newElement);return this; }

這里的accumulator用來將流中的值疊加入容器中.

combiner方法與reduce方法類似,將兩個容器合并。由于Collector支持并發操作,如果不將多的容器合并,必然會導致數據的混亂。如果僅僅在串行執行,此步驟可以省略。這里,使用了StringJoiner::merge來實現,最后返回的是

public StringJoiner merge(StringJoiner other) {Objects.requireNonNull(other);if (other.value != null) {final int length = other.value.length();、StringBuilder builder = prepareBuilder();builder.append(other.value, other.prefix.length(), length);}return this; }

在收集階段,Collector被combiner方法成對合并進一個容器,直到最后只剩一個容器為止.

最后,finisher方法將StringJoiner轉換為最后的結果,將toString方法內聯到方法鏈的末端,這就將 StringCombiners轉換成了我們想要的字符串。

public String toString() {if (value == null) {return emptyValue;} else {if (suffix.equals("")) {return value.toString();} else {int initialLength = value.length();String result = value.append(suffix).toString();// reset value to pre-append initialLengthvalue.setLength(initialLength);return result;}} }

這樣,我們就完成了Collector的自定義,好像還有一點我們忽略掉了,那就是Collector的特征。正是忽略了這點,在自定義時,給自己挖了一個坑。關于Characteristics這個Enum看下官方文檔吧,前面已經提到這里不再多述。

Collector自定義起來,也不是特別的麻煩,不過要明確以下幾點:

  • 參數類型:這里最重要的是指定累加器的類型,一般都是自定義的過渡類?
  • 待收集元素的類型:T;
  • 累加器的類型:A;
  • 最終結果的類型:R。
  • 累加器的邏輯
  • 最終結果的轉換
  • Collector特征的選擇
  • 自定義Collector

    現在有個簡單的需求,求一段數字的和,如果是奇數,直接相加;如果是偶數,乘以2后再相加。這樣的場景下,Collector類庫中的收集器不能滿足我們的需求,我們只能夠自己定義了。

    1.自定義類作為過渡容器

    我們先定義一個類IntegerSum作為過渡容器。這里所說的容器并不一定是集合,只是對數據的臨時存儲,稱之為過渡容器。在IntegerSum類內,定義了3個方法:

    • doSum:作為累加器,實現求和操作
    • doCombine:作為combine,將兩個容器合并
    • toValue:作為finisher,將IntegerSum轉為所需要的結果Integer
    public class IntegerSum {?Integer sum;public IntegerSum(Integer sum) {this.sum = sum;}public IntegerSum doSum(Integer item) {if (item % 2 == 0) {this.sum += item * 2;} else {this.sum += item;}return this;}public IntegerSum doCombine(IntegerSum it) {this.sum += it.sum;return this;}public Integer toValue() {return this.sum;} }

    明確參數類型

    • 待收集元素的類型:Integer
    • 累加器的類型:IntegerSum
    • 最終結果的類型:Integer

    實現Collector接口

    Integer integerSum = Stream.of(1, 2, 3, 4).collect(new Collector<Integer, IntegerSum, Integer>() {@Overridepublic Supplier<IntegerSum> supplier() {return () -> new IntegerSum(2);}@Overridepublic BiConsumer<IntegerSum, Integer> accumulator() {return IntegerSum::doSum;}@Overridepublic BinaryOperator<IntegerSum> combiner() {return IntegerSum::doCombine;}@Overridepublic Function<IntegerSum, Integer> finisher() {return IntegerSum::toValue;}@Overridepublic Set<Characteristics> characteristics() {Set<Collector.Characteristics> CH_NOID = Collections.emptySet();return CH_NOID;}}); System.out.println("integerSum: " + integerSum); // 打印結果:integerSum: 18

    在實現Collector接口時,我們通過方法引用的方式,指定了Collector的四部分的實現形式,見代碼。對于Characteristics,并未對Collecotor設置特征。

    這樣一個簡單的自定義Collector,就實現了。如果有興趣,你可以試一下。
    ---------------------?
    作者:行云間?
    來源:CSDN?
    原文:https://blog.csdn.net/io_field/article/details/54971555?
    版權聲明:本文為博主原創文章,轉載請附上博文鏈接!

    總結

    以上是生活随笔為你收集整理的Java 8系列之重构和定制收集器的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    主站蜘蛛池模板: 毛片成人 | 欧美精品一卡 | 日韩在线91 | 五月婷婷中文字幕 | 91热久久| 日韩av专区片 | 黄色片久久久 | 欧洲成人在线视频 | 国产白嫩美女无套久久 | 99久久精品无码一区二区毛片 | av黄色网| 国产a区| 亚洲熟女一区二区三区 | 国产午夜福利视频在线观看 | 污污视频在线免费看 | 欧美精品电影一区二区 | 亚洲精品白浆高清久久久久久 | 综合一区在线 | 全部孕妇毛片丰满孕妇孕交 | 无遮挡又爽又刺激的视频 | www.亚洲激情| 99色这里只有精品 | 精品女厕偷拍一区二区 | 青青草97国产精品麻豆 | 中文字幕第一页av | 日韩精品一二三四区 | 日韩免费视频一区二区视频在线观看 | 日韩精品一区二区三区在线 | 日韩av不卡在线 | 草草在线观看视频 | 欧美无砖砖区免费 | 日本一区二区视频在线观看 | 男人天堂2019 | 日韩一级在线观看 | 男人天堂国产 | 日韩黄色免费视频 | 三级免费| 乳揉みま痴汉4在线播放 | 成人99| 免费精品在线观看 | 午夜日韩 | 五月天婷婷爱 | 成人免费看类便视频 | 日韩视频在线免费观看 | www欧美色 | 黄色大片网址 | 欧美日韩性生活视频 | 亚洲福利一区 | 欧美亚洲第一区 | 国产精品国产精品国产专区不片 | 日韩区欧美区 | 亚洲欧洲色 | 欧美一级淫片 | 国产欧美一区二区三区沐欲 | 性做久久久久久久免费看 | 日日躁夜夜躁白天躁晚上躁91 | 波多野结衣欧美 | 国产成人无码一区二区在线播放 | 日少妇b| 麻豆精品一区 | 亚洲图片欧美在线看 | 亚洲性欧美色 | 3o一40一50一6o女人毛片 | 乡村乱淫| 精品福利视频导航 | 亚洲国产成人精品一区二区三区 | 爱爱视频欧美 | 日本黄大片在线观看 | 日韩欧美少妇 | 色老头一区二区三区在线观看 | 丝袜黄色片 | 露出调教羞耻91九色 | 精品不卡一区 | xvideos永久免费入口 | 800av在线视频 | 国产中文字幕一区 | 久草视频免费 | 欧美一区永久视频免费观看 | 成人av免费| 欧美三级中文字幕 | 欧美精品二区三区四区免费看视频 | 国产精品一区二区av日韩在线 | 在线播放少妇奶水过盛 | 亚洲小视频网站 | 草民午夜理伦三级 | 内谢少妇xxxxx8老少交视频 | 日本啊v在线 | 露胸app| 99久久99久久精品免费看蜜桃 | 国内露脸中年夫妇交换 | 日韩bbw | 久章草影院 | 欧美三区在线 | 精品视频一二三 | 日产精品一区二区 | 国产精品一线 | 精品视频入口 | 亚洲在线激情 | 香蕉久久夜色 |