欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

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),并應用一些附加邏輯,將它們連接起來,等等)。

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

Collectors

所有預定義的實現(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());

集合不包含重復的元素。如果我們的集合包含彼此相等的元素,則它們只在結(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ā)生什么呢?與toSet相反,toMap不會默默地過濾重復項,這是可以理解的,因為它如何確定為該鍵選擇哪個值?

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

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

在key沖突的情況下,我們應該使用另一個簽名的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。現(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)文章

  • java如何實現(xiàn)項目啟動時執(zhí)行指定方法

    java如何實現(xiàn)項目啟動時執(zhí)行指定方法

    這篇文章主要為大家詳細介紹了java項目如何啟動時執(zhí)行指定方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Java經(jīng)典面試題匯總:Mybatis

    Java經(jīng)典面試題匯總:Mybatis

    本篇總結(jié)的是Mybatis框架相關(guān)的面試題,后續(xù)會持續(xù)更新,希望我的分享可以幫助到正在備戰(zhàn)面試的實習生或者已經(jīng)工作的同行,如果發(fā)現(xiàn)錯誤還望大家多多包涵,不吝賜教,謝謝
    2021-07-07
  • 如何在Java中實現(xiàn)一個散列表

    如何在Java中實現(xiàn)一個散列表

    這篇文章主要介紹了如何在Java中實現(xiàn)一個散列表,建一個HashMap,以String類型為Key,Int類型為Value,下文具體的操作過程需要的小伙伴可以參考一下
    2022-04-04
  • Java OpenCV利用KNN算法實現(xiàn)圖像背景移除

    Java OpenCV利用KNN算法實現(xiàn)圖像背景移除

    這篇文章主要為大家介紹了Java OpenCV利用K最鄰近(KNN,K-NearestNeighbor)分類算法實現(xiàn)圖像背景移除的示例代碼,需要的可以參考一下
    2022-01-01
  • ToStringBuilder類的一些心得

    ToStringBuilder類的一些心得

    ToStringBuilder類的一些心得,需要的朋友可以參考一下
    2013-02-02
  • 簡析Java中的util.concurrent.Future接口

    簡析Java中的util.concurrent.Future接口

    這篇文章主要介紹了簡析Java中的util.concurrent.Future接口,作者把future歸結(jié)為在未來得到目標對象的占位符,需要的朋友可以參考下
    2015-07-07
  • Spring自動裝配與掃描注解代碼詳解

    Spring自動裝配與掃描注解代碼詳解

    這篇文章主要介紹了Spring自動裝配與掃描注解代碼詳解,具有一定借鑒價值,需要的朋友可以參考下。
    2017-12-12
  • Javaweb 定時器功能代碼實例

    Javaweb 定時器功能代碼實例

    這篇文章主要介紹了Javaweb 定時器功能代碼實例,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下
    2020-04-04
  • Spring @Value 設(shè)置默認值的實現(xiàn)

    Spring @Value 設(shè)置默認值的實現(xiàn)

    這篇文章主要介紹了Spring @Value 設(shè)置默認值的實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-09-09
  • Java微服務(wù)的打包問題解決

    Java微服務(wù)的打包問題解決

    本文主要介紹了Java微服務(wù)的打包問題解決,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2023-06-06

最新評論