最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java?8中的Collectors?API介紹

 更新時間:2022年04月14日 14:52:28   作者:?sofia??  
這篇文章主要介紹了Java?8中的Collectors?API,Stream.collect()是Java?8的流API的終端方法之一。它允許我們對流實例中保存的數(shù)據(jù)元素執(zhí)行可變折疊操作,下文相關(guān)內(nèi)容需要的小伙伴可以參考一下

Stream.Collect() 方法

Stream.collect()是Java 8的流API的終端方法之一。它允許我們對流實例中保存的數(shù)據(jù)元素執(zhí)行可變折疊操作(將元素重新打包到某些數(shù)據(jù)結(jié)構(gòu),并應(yīng)用一些附加邏輯,將它們連接起來,等等)。

此操作的策略通過收集器接口實現(xiàn)提供。

Collectors

所有預(yù)定義的實現(xiàn)都可以在Collectors類中找到。通常使用以下靜態(tài)導入來提高可讀性:

import static java.util.stream.Collectors.*;

我們也可以使用我們選擇的單一導入收集器collectors:

import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;
import static java.util.stream.Collectors.toSet;

在以下示例中,我們將重用以下list:

List<String> givenList = Arrays.asList("a", "bb", "ccc", "dd");

Collectors.ToList()

toList收集器可用于將所有流元素收集到列表實例中。需要記住的重要一點是,我們不能用這種方法假設(shè)任何特定的列表實現(xiàn)。如果我們想對此有更多的控制,我們可以使用toCollection。

讓我們創(chuàng)建一個表示元素序列的流實例,然后將它們收集到一個列表實例中:

List<String> result = givenList.stream()
  .collect(toList());

Collectors.ToUnmodifiableList()

Java 10引入了一種方便的方法,將流元素累積到一個不可修改的列表中:

List<String> result = givenList.stream()
  .collect(toUnmodifiableList());

現(xiàn)在,如果我們試圖修改結(jié)果列表,我們將得到一個UnsupportedOperationException

assertThatThrownBy(() -> result.add("foo"))
  .isInstanceOf(UnsupportedOperationException.class);

Collectors.ToSet()

toSet收集器可用于將所有流元素收集到集合實例中。需要記住的重要一點是,我們不能用這種方法假設(shè)任何特定的集合實現(xiàn)。如果我們想對此有更多的控制,我們可以使用toCollection。

讓我們創(chuàng)建一個表示元素序列的流實例,然后將它們收集到一個集合實例中:

Set<String> result = givenList.stream()
  .collect(toSet());

集合不包含重復(fù)的元素。如果我們的集合包含彼此相等的元素,則它們只在結(jié)果集中出現(xiàn)一次:

List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
Set<String> result = listWithDuplicates.stream().collect(toSet());
assertThat(result).hasSize(4);

Collectors.ToUnmodifiableSet()

自Java 10以來,我們可以使用toUnmodifiableSet()收集器輕松創(chuàng)建一個不可修改的集:

Set<String> result = givenList.stream()
  .collect(toUnmodifiableSet());

任何修改結(jié)果集的嘗試都將以不支持操作異常告終:

assertThatThrownBy(() -> result.add("foo"))
  .isInstanceOf(UnsupportedOperationException.class);

Collectors.ToCollection()

正如我們已經(jīng)指出的,在使用toSettoList收集器時,我們不能對它們的實現(xiàn)進行任何假設(shè)。如果我們想使用自定義實現(xiàn),我們需要將toCollection收集器與我們選擇的提供的集合一起使用。

讓我們創(chuàng)建一個表示元素序列的流實例,然后將它們收集到LinkedList實例中:

List<String> result = givenList.stream()
  .collect(toCollection(LinkedList::new))

請注意,這不適用于任何不可變的集合。在這種情況下,我們需要編寫自定義收集器實現(xiàn)或使用CollectionAndThen

Collectors.ToMap()

toMap收集器可用于將流元素收集到映射實例中。為此,我們需要提供兩個功能:

  • keyMapper
  • valueMapper

我們將使用keyMapper從流元素中提取映射鍵,使用valueMapper提取與給定鍵關(guān)聯(lián)的值。

讓我們將這些元素收集到一個映射中,該映射將字符串存儲為鍵,長度存儲為值:

Map<String, Integer> result = givenList.stream()
  .collect(toMap(Function.identity(), String::length))

Function.identity()只是定義接受并返回相同值的函數(shù)的快捷方式。

那么,如果我們的集合包含重復(fù)的元素,會發(fā)生什么呢?與toSet相反,toMap不會默默地過濾重復(fù)項,這是可以理解的,因為它如何確定為該鍵選擇哪個值?

List<String> listWithDuplicates = Arrays.asList("a", "bb", "c", "d", "bb");
assertThatThrownBy(() -> {
    listWithDuplicates.stream().collect(toMap(Function.identity(), String::length));
}).isInstanceOf(IllegalStateException.class);

請注意,toMap甚至不計算這些值是否相等。如果它看到重復(fù)的key,它會立即拋出一個非法狀態(tài)異常。

在key沖突的情況下,我們應(yīng)該使用另一個簽名的toMap

Map<String, Integer> result = givenList.stream()
  .collect(toMap(Function.identity(), String::length, (item, identicalItem) -> item));

這里的第三個參數(shù)是BinaryOperator,我們可以在其中指定希望如何處理碰撞。在本例中,我們只選擇這兩個沖突的值中的任何一個,因為我們知道相同的字符串也總是具有相同的長度。

Collectors.ToUnmodifiableMap()

與列表和集合類似,Java 10引入了一種將流元素收集到不可修改映射中的簡單方法:

Map<String, Integer> result = givenList.stream()
  .collect(toMap(Function.identity(), String::length))

正如我們所見,如果我們試圖在結(jié)果映射中添加一個新條目,我們將得到一個不支持的操作異常:

assertThatThrownBy(() -> result.put("foo", 3))
  .isInstanceOf(UnsupportedOperationException.class);

Collectors.CollectingAndThen()

CollectionAndThen是一個特殊的收集器,允許我們在收集結(jié)束后立即對結(jié)果執(zhí)行另一個操作。

讓我們將流元素收集到列表實例,然后將結(jié)果轉(zhuǎn)換為ImmutableList實例:

List<String> result = givenList.stream()
  .collect(collectingAndThen(toList(), ImmutableList::copyOf))

Collectors.Joining()

Joining收集器可用于joining Stream<String> 元素。

我們可以通過以下方式將它們結(jié)合在一起:

String result = givenList.stream()
  .collect(joining());

結(jié)果:

"abbcccdd"

我們還可以指定自定義分隔符、前綴和后綴:

String result = givenList.stream()
  .collect(joining(" "));

結(jié)果:

"a bb ccc dd"

也可這樣寫:

String result = givenList.stream()
  .collect(joining(" ", "PRE-", "-POST"));

結(jié)果:

"PRE-a bb ccc dd-POST"

Collectors.Counting()

Counting是一個簡單的收集器,允許對所有流元素進行計數(shù)。

現(xiàn)在我們可以寫:

Long result = givenList.stream()
  .collect(counting());

Collectors.SummarizingDouble/Long/Int()

SummaringDouble/Long/Int是一個收集器,它返回一個特殊的類,該類包含有關(guān)提取元素流中數(shù)字數(shù)據(jù)的統(tǒng)計信息。

我們可以通過以下操作獲得有關(guān)字符串長度的信息:

DoubleSummaryStatistics result = givenList.stream()
  .collect(summarizingDouble(String::length));

在這種情況下,以下是正確的:

assertThat(result.getAverage()).isEqualTo(2);
assertThat(result.getCount()).isEqualTo(4);
assertThat(result.getMax()).isEqualTo(3);
assertThat(result.getMin()).isEqualTo(1);
assertThat(result.getSum()).isEqualTo(8);

Collectors.AveragingDouble/Long/Int()

AveragingDouble/Long/Int是一個收集器,它只返回提取元素的平均值。

我們可以通過以下操作獲得平均字符串長度:

Double result = givenList.stream()
  .collect(averagingDouble(String::length));

Collectors.SummingDouble/Long/Int()

SummingDouble/Long/Int是一個收集器,它只返回提取元素的總和。

我們可以通過以下操作得到所有字符串長度的總和:

Double result = givenList.stream()
  .collect(summingDouble(String::length));

Collectors.MaxBy()/MinBy()

MaxBy/MinBy收集器根據(jù)提供的比較器實例返回流的最大/最小元素。

我們可以通過以下方式選擇最大的元素:

Optional<String> result = givenList.stream()
  .collect(maxBy(Comparator.naturalOrder()));

我們可以看到返回的值被包裝在一個可選的實例中。這迫使用戶重新考慮空的收集角落案例。

Collectors.GroupingBy()

GroupingBy collector用于按某些屬性對對象進行分組,然后將結(jié)果存儲在Map實例中。

我們可以按字符串長度對它們進行分組,并將分組結(jié)果存儲在集合實例中:

Map<Integer, Set<String>> result = givenList.stream()
  .collect(groupingBy(String::length, toSet()));

結(jié)果是true:

assertThat(result)
  .containsEntry(1, newHashSet("a"))
  .containsEntry(2, newHashSet("bb", "dd"))
  .containsEntry(3, newHashSet("ccc"));

我們可以看到groupingBy方法的第二個參數(shù)是收集器。此外,我們可以自由使用我們選擇的任何收集器。

Collectors.PartitioningBy()

PartitioningBy是groupingBy的一種特殊情況,它接受謂詞實例,然后將流元素收集到Map實例中,Map實例將布爾值存儲為鍵,將集合存儲為值。在“true”鍵下,我們可以找到與給定謂詞匹配的元素集合,在“false”鍵下,我們可以找到與給定謂詞不匹配的元素集合。

我們可以寫:

Map<Boolean, List<String>> result = givenList.stream()
  .collect(partitioningBy(s -> s.length() > 2))

在Map中的結(jié)果:

{false=["a", "bb", "dd"], true=["ccc"]}

Collectors.Teeing()

讓我們使用到目前為止所學的收集器,從給定流中找出最大和最小數(shù):

List<Integer> numbers = Arrays.asList(42, 4, 2, 24);
Optional<Integer> min = numbers.stream().collect(minBy(Integer::compareTo));
Optional<Integer> max = numbers.stream().collect(maxBy(Integer::compareTo));
// do something useful with min and max

在這里,我們使用兩個不同的收集器,然后將這兩個收集器的結(jié)果結(jié)合起來,創(chuàng)造出一些有意義的東西。在Java12之前,為了涵蓋此類用例,我們必須對給定流進行兩次操作,將中間結(jié)果存儲到臨時變量中,然后將這些結(jié)果合并。

幸運的是,Java12提供了一個內(nèi)置收集器,代表我們處理這些步驟;我們所要做的就是提供兩個采集器和組合器功能。

由于這種新的收集器將給定的流轉(zhuǎn)向兩個不同的方向,因此稱為T形:

numbers.stream().collect(teeing(
  minBy(Integer::compareTo), // The first collector
  maxBy(Integer::compareTo), // The second collector
  (min, max) -> // Receives the result from those collectors and combines them
));

Custom Collectors

如果我們想編寫自己的收集器實現(xiàn),我們需要實現(xiàn)收集器接口,并指定其三個通用參數(shù):

public interface Collector<T, A, R> {...}
  • T–可供收集的對象類型
  • A–可變累加器對象的類型
  • R–最終結(jié)果的類型

讓我們編寫一個示例收集器,用于將元素收集到ImmutableSet實例中。我們首先指定正確的類型:

private class ImmutableSetCollector<T>
  implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {...}

因為我們需要一個可變集合來處理內(nèi)部集合操作,所以不能使用ImmutableSet。相反,我們需要使用一些其他可變集合,或任何其他可以臨時為我們積累對象的類。在這種情況下,我們將使用ImmutableSet?,F(xiàn)在我們需要實現(xiàn)5種方法:

  • Supplier<ImmutableSet.Builder<T>> supplier()
  • BiConsumer<ImmutableSet.Builder<T>, T> accumulator()
  • BinaryOperator<ImmutableSet.Builder<T>> combiner()
  • Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher()
  • Set<Characteristics> characteristics()

supplier()方法返回一個生成空累加器實例的Supplier實例。所以在這種情況下,我們可以簡單地寫:

@Override
public Supplier<ImmutableSet.Builder<T>> supplier() {
    return ImmutableSet::builder;
}

acculator()方法返回一個函數(shù),該函數(shù)用于向現(xiàn)有acculator對象添加新元素。讓我們使用生成器的add方法:

@Override
public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
    return ImmutableSet.Builder::add;
}

combiner()方法返回一個用于將兩個累加器合并在一起的函數(shù):

@Override
public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
    return (left, right) -> left.addAll(right.build());
}

finisher()方法返回一個函數(shù),用于將累加器轉(zhuǎn)換為最終結(jié)果類型。所以在這種情況下,我們只使用Builder的構(gòu)建方法:

@Override
public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
    return ImmutableSet.Builder::build;
}

characteristics()方法用于為Stream提供一些用于內(nèi)部優(yōu)化的附加信息。在這種情況下,我們不會注意元素在集合中的順序。

@Override public Set<Characteristics> characteristics() {
    return Sets.immutableEnumSet(Characteristics.UNORDERED);
}

以下是完整的實現(xiàn)和用法:

public class ImmutableSetCollector<T>
  implements Collector<T, ImmutableSet.Builder<T>, ImmutableSet<T>> {

@Override
public Supplier<ImmutableSet.Builder<T>> supplier() {
    return ImmutableSet::builder;
}

@Override
public BiConsumer<ImmutableSet.Builder<T>, T> accumulator() {
    return ImmutableSet.Builder::add;
}

@Override
public BinaryOperator<ImmutableSet.Builder<T>> combiner() {
    return (left, right) -> left.addAll(right.build());
}

@Override
public Function<ImmutableSet.Builder<T>, ImmutableSet<T>> finisher() {
    return ImmutableSet.Builder::build;
}

@Override
public Set<Characteristics> characteristics() {
    return Sets.immutableEnumSet(Characteristics.UNORDERED);
}

public static <T> ImmutableSetCollector<T> toImmutableSet() {
    return new ImmutableSetCollector<>();
}

最后在action中:

List<String> givenList = Arrays.asList("a", "bb", "ccc", "dddd");

ImmutableSet<String> result = givenList.stream()
  .collect(toImmutableSet());

到此這篇關(guān)于Java 8中的Collectors API介紹的文章就介紹到這了,更多相關(guān) Collectors API 內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 基于Process#waitFor()阻塞問題的解決

    基于Process#waitFor()阻塞問題的解決

    這篇文章主要介紹了Process#waitFor()阻塞問題的解決,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2021-12-12
  • Java數(shù)據(jù)結(jié)構(gòu)通關(guān)時間復(fù)雜度和空間復(fù)雜度

    Java數(shù)據(jù)結(jié)構(gòu)通關(guān)時間復(fù)雜度和空間復(fù)雜度

    對于一個算法,其時間復(fù)雜度和空間復(fù)雜度往往是相互影響的,當追求一個較好的時間復(fù)雜度時,可能會使空間復(fù)雜度的性能變差,即可能導致占用較多的存儲空間,這篇文章主要給大家介紹了關(guān)于Java時間復(fù)雜度、空間復(fù)雜度的相關(guān)資料,需要的朋友可以參考下
    2022-05-05
  • Java二維碼登錄流程實現(xiàn)代碼(包含短地址生成,含部分代碼)

    Java二維碼登錄流程實現(xiàn)代碼(包含短地址生成,含部分代碼)

    近年來,二維碼的使用越來越風生水起,本篇文章主要介紹了Java二維碼登錄流程實現(xiàn)代碼,其中包含短地址生成,有興趣的可以了解一下。
    2016-12-12
  • Java?I/O流使用示例詳解

    Java?I/O流使用示例詳解

    Java.io?包幾乎包含了所有操作輸入、輸出需要的類。所有這些流類代表了輸入源和輸出目標。本文將通過示例為大家詳細講講?I/O流的使用教程,需要的可以參考一下
    2022-08-08
  • SpringMVC @ControllerAdvice使用場景

    SpringMVC @ControllerAdvice使用場景

    這篇文章主要介紹了SpringMVC @ControllerAdvice使用場景,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2019-11-11
  • java實現(xiàn)LFU算法的示例代碼

    java實現(xiàn)LFU算法的示例代碼

    LFU(Least Frequently Used)算法根據(jù)數(shù)據(jù)的歷史訪問頻率來淘汰數(shù)據(jù),其核心思想是“如果數(shù)據(jù)過去被訪問多次,那么將來被訪問的頻率也更高”,本文為大家整理了Java實現(xiàn)LFU算法的示例代碼,需要的可以參考下
    2023-11-11
  • javaweb圖書商城設(shè)計之購物車模塊(3)

    javaweb圖書商城設(shè)計之購物車模塊(3)

    這篇文章主要為大家詳細介紹了javaweb圖書商城設(shè)計之購物車模塊的相關(guān)資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • SpringBoot進行Web開發(fā)的實現(xiàn)

    SpringBoot進行Web開發(fā)的實現(xiàn)

    Spring?Boot讓我們可以快速構(gòu)建項目并運行web應(yīng)用,大大簡化了Spring的復(fù)雜配置,本文主要介紹了SpringBoot進行Web開發(fā)的實現(xiàn),感興趣的可以了解一下
    2023-10-10
  • 如何解決HttpServletRequest.getInputStream()多次讀取問題

    如何解決HttpServletRequest.getInputStream()多次讀取問題

    這篇文章主要介紹了如何解決HttpServletRequest.getInputStream()多次讀取問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • mybatis源碼解讀之executor包語句處理功能

    mybatis源碼解讀之executor包語句處理功能

    這篇文章主要介紹了executor包語句處理功能,mybatis中支持三種語句類型,不同語句類型支持的變量符號不同,下文詳細內(nèi)容,需要的小伙伴可以參考一下
    2022-02-02

最新評論

辽源市| 珠海市| 墨玉县| 壤塘县| 都昌县| 海丰县| 阿尔山市| 于都县| 彩票| 寻乌县| 文成县| 昌都县| 阿鲁科尔沁旗| 香格里拉县| 乌兰浩特市| 松江区| 汕尾市| 渝中区| 扎囊县| 隆回县| 鄂伦春自治旗| 阜南县| 凯里市| 云阳县| 榆树市| 汕头市| 潮安县| 英吉沙县| 大方县| 武夷山市| 扎赉特旗| 呼玛县| 九寨沟县| 龙井市| 阜宁县| 博罗县| 长治县| 宝鸡市| 宣武区| 西乌珠穆沁旗| 崇州市|