一緒Java8を学ぶために(7) - ストリーム(中)

では一起来学Java8(七)——Stream(上)、私たちは、Streamオブジェクトの一般的な方法と使用方法を学びました。今の深い知識を取るStream.collect()の使用を

基本的な使い方を集めます

収集され、グループ化されたストリーム要素であるコレクションを収集することを意味し、オブジェクトの新しいコレクションが返されます。簡単な例ではまず見て:

public class CollectTest {

    @Data
    @AllArgsConstructor
    static class Goods {
        private String goodsName;
        private int price;
    }
    
    public static void main(String[] args) {
        List<Goods> list = Arrays.asList(
                new Goods("iphoneX", 4000)
                , new Goods("mate30 pro", 5999)
                , new Goods("redmek20", 2999)
                );
        List<String> nameList = list.stream()
            .map(Goods::getGoodsName)
            .collect(Collectors.toList());
    }

}复制代码

この例では、商品名は、mapメソッドによって返され、その後、Listオブジェクトに商品名を入れました。

ソースを表示見つけ、プロセスは2つのオーバーロードされたメソッド組成物で構成されて集めます。

  • 方法1:
<R> R collect(Supplier<R> supplier,
                  BiConsumer<R, ? super T> accumulator,
                  BiConsumer<R, R> combiner);复制代码

  • 方法2:
<R, A> R collect(Collector<? super T, A, R> collector);复制代码

最も広く用いられる方法2であることを特徴とする請求コレクタは、同様に提供されるので、この方法は、ショートカット法として見ることができ、これらの3つのパラメータを、推測する、又は実装に対応する基礎となるプロセスを使用することは容易です。Supplier supplier, BiConsumer accumulator, BiConsumer combiner

私たちはして開始することができますcollect(Collector collector)使用状況を知るためのこのプロセスを通過、起動を開始します。

コレクター

Stream.collect(Collector collector)コレクターパラメータオブジェクトのメソッドは、主にCollectorsクラスを提供します。静的メソッドの一連を含んコレクタークラスは、オブジェクトに対して下記のように一般的に使用される方法をコレクタを返します。

メソッド名 説明
averagingXX アベレージ
カウント セット内の要素の数を求めて
groupingBy 収集グループ
接合 コレクション要素スプライシング
マッピング パケット中に値を再マッピングすることができます
maxBy 最大値を求めて
minBy 最小の場合
partitioningBy 要素を分割
縮小 誘導
summarizingXX 集まります
toCollection オブジェクトのコレクションに変換
toConcurrentMap ConcurrentMapに変換
ToListメソッド リストを変換します
toMap 地図に変換
toSet セットに変換

ここでは、各方法の面で彼の有用性をオフにしてください。

averagingXX

averagingDouble、a​​veragingInt、averagingLong含むaveragingXX。彼らは平均を表します。

double averagingInt = Stream.of(1, 2, 3)
        .collect(Collectors.averagingInt(val -> val));
System.out.println("averagingInt:" + averagingInt);

double averagingLong = Stream.of(10L, 21L, 30L)
        .collect(Collectors.averagingLong(val -> val));
System.out.println("averagingLong:" + averagingLong);

double averagingDouble = Stream.of(0.1, 0.2, 0.3)
        .collect(Collectors.averagingDouble(val -> val));
System.out.println("averagingDouble:" + averagingDouble);复制代码

それらのパラメータは、要素の発現ラムダストリーム・パラメータは、平均する値を返す、請求あなたは、ラムダ式を使用して調製することができる、機能インタフェースです。これは列子が求めている商品の平均を下回っています。

List<Goods> list = Arrays.asList(
                new Goods("iphoneX", 4000)
                , new Goods("mate30 pro", 5999)
                , new Goods("redmek20", 2999)
                );
        
double avgPrice = list.stream()
    .collect(Collectors.averagingInt(goods -> goods.getPrice()));
System.out.println("商品的平均价格:" + avgPrice);复制代码

summingXX

そしてaveragingXX同様に、summingXX要素法は、設定された値の和を見つけるために使用されます。

double summingInt = Stream.of(1, 2, 3)
        .collect(Collectors.summingInt(val -> val));
System.out.println("summingInt:" + summingInt);

double summingLong = Stream.of(10L, 21L, 30L)
        .collect(Collectors.summingLong(val -> val));
System.out.println("summingLong:" + summingLong);

double summingDouble = Stream.of(0.1, 0.2, 0.3)
        .collect(Collectors.summingDouble(val -> val));
System.out.println("summingDouble:" + summingDouble);复制代码

印刷:

summingInt:6.0
summingLong:61.0
summingDouble:0.6复制代码

カウント()

)(カウントするコレクション中の要素の数を返します。

long count = Stream.of(1,2,3,4,5)
        .collect(Collectors.counting());
System.out.println("count:" + count); // 5复制代码

summarizingXX

上記の私は、同時に3つのすべてにそれを行う方法の数を取得したい場合、あなたはsummarizingXXを使用することができ、(総需要)をカウント、averagingXX(平均)、summingXX(合計)について話しました。

IntSummaryStatistics summarizingInt = Stream.of(1, 2, 3)
                .collect(Collectors.summarizingInt(val -> val));
System.out.println("平均值:" + summarizingInt.getAverage());
System.out.println("总个数:" + summarizingInt.getCount());
System.out.println("总和:" + summarizingInt.getSum());
System.out.println("最大值:" + summarizingInt.getMax());
System.out.println("最小值:" + summarizingInt.getMin());复制代码

印刷:

平均值:2.0
总个数:3
总和:6
最大值:3
最小值:1复制代码

IntSummaryStatisticsが内部オブジェクトに、そのオブジェクト内の別の統計情報を取得することができる統計結果をsummarizingInt。

groupingBy()

groupingByは()は、3つのオーバーロードされたメソッド組成物によってグループ化された要素の集合であります

  • 過負荷1:groupingBy(機能)
  • 過負荷2:groupingBy(機能、コレクタ)
  • 重载3:groupingBy(機能、サプライヤー、コレクタ)

過過負荷呼び出し1項2、過負荷3は、このように、最終的に3をオーバーロードするために実装、過負荷2を呼び出します。

まず、ルックオーバーロードされたgroupingBy(Function)用法、新しいリストにデフォルトのパケットのこの方法は、このタイプの製品の次の例では、リスト内の商品の同じ種類に分類されています。

@Data
@AllArgsConstructor
static class Goods {
    private String goodsName;
    // 类型,1:手机,2:电脑
    private int type;
    @Override
    public String toString() {
        return goodsName;
    }
}

public static void main(String[] args) {
    List<Goods> list = Arrays.asList(
            new Goods("iphoneX", 1)
            , new Goods("mate30 pro", 1)
            , new Goods("thinkpad T400", 2)
            , new Goods("macbook pro", 2)
            );
    
    Map<Integer, List<Goods>> goodsListMap = list.stream()
        .collect(Collectors.groupingBy(Goods::getType));
    goodsListMap.forEach((key, value) -> {
        System.out.println("类型" + key + ":" + value);
    });
}复制代码

印刷:

类型1:[iphoneX, mate30 pro]
类型2:[thinkpad T400, macbook pro]复制代码

上記といえばgroupingBy(Function)、実際に呼ばれるgroupingBy(Function, Collector)2番目のパラメータがあり、Collectorデフォルトでどこに変換決定toList()、参照groupingBy(Function)ソースコード:

public static <T, K> Collector<T, ?, Map<K, List<T>>>
    groupingBy(Function<? super T, ? extends K> classifier) {
        return groupingBy(classifier, toList());
    }复制代码

だから我々は呼び出すことができgroupingBy(Function, Collector)、我々はセットに変換する必要がある要素は、あなたが書くことができると仮定して、コレクタを指定し、手動で:

Map<Integer, Set<Goods>> goodsListMap = list.stream()
        .collect(Collectors.groupingBy(Goods::getType, Collectors.toSet()));复制代码

ビューオーバーロードされたメソッドのソース2、その通話は3オーバーロードが見つかりました:

public static <T, K, A, D>
    Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,
                                          Collector<? super T, A, D> downstream) {
        return groupingBy(classifier, HashMap::new, downstream);
    }复制代码

前記Goods::getType対応する分類器、Collectors.toSet()対応する下流。そのパラメータの真ん中のHashMap::new意味が明確であり、それは、我々はのLinkedHashMapを変更したい場合は、書き込みMap実装クラスのリターンです。

LinkedHashMap<Integer, Set<Goods>> goodsListMap = list.stream()
        .collect(Collectors.groupingBy(Goods::getType, LinkedHashMap::new, Collectors.toSet()));
        复制代码

これは、ヘビーデューティー使用3です。

この方法は、コードの途中からヘビーデューティ3に基づいてGroupingByConcurrentコレクターを変更ConcurrentHashMap::newして。

public static <T, K>
    Collector<T, ?, ConcurrentMap<K, List<T>>>
    groupingByConcurrent(Function<? super T, ? extends K> classifier) {
        return groupingByConcurrent(classifier, ConcurrentHashMap::new, toList());
    }复制代码

コレクターパラメータgroupingBy方法だけでなく、することができToListメソッド()、toSet()、それはまた、我々が変換される前に、より柔軟な使用を持っているだけで、あなたはそんなにプロパティをしたくない場合は、フォーム、値は、オブジェクトのコレクションに格納されています私たちが望むことを意味商品名,,するオブジェクトたいキー商品タイプで、値が商品のコレクションの名前です。Map > Map >

この時間は、Collectors.mapping()我々が使用する、便利になるgroupingBy(Function, Collector)2番目のパラメータが渡され、メソッドをCollectors.mapping()

Map<Integer, List<String>> goodsListMap = 
list.stream()
    .collect(
         Collectors.groupingBy(
            Goods::getType, 
            Collectors.mapping(Goods::getGoodsName, Collectors.toList())
         )
    );复制代码

マッピング()メソッドは、最初のパラメータは、プロパティ戻り、戻りコレクションを指定する第2のパラメータを指定し、2つのパラメータを取ります。

接合

素子の接合方法は、ストリームを一緒にスプライスすることができます。

List<String> list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining());
System.out.println(str); // 打印:helloworld复制代码

また、区切り文字を指定することができます。

List<String> list = Arrays.asList("hello", "world");
String str = list.stream().collect(Collectors.joining(","));
System.out.println(str); // 打印:hello,world复制代码

また、Stringクラス参加の方法を提供し、機能は同じです

String str2 = String.join(",", list);
System.out.println(str2);复制代码

maxBy&minBy

  • maxBy:ストリームで最大の要素を見つけます
@Data
@AllArgsConstructor
static class Goods {
    private String goodsName;
    private int price;
}

public static void main(String[] args) {
    List<Goods> list = Arrays.asList(
            new Goods("iphoneX", 4000)
            , new Goods("mate30 pro", 5999)
            , new Goods("redmek20", 2999)
            );
    
    Goods maxPriceGoods = list.stream()
        .collect(
            Collectors.maxBy(
                Comparator.comparing(Goods::getPrice)
            )
        )
        .orElse(null);
    System.out.println("最贵的商品:" + maxPriceGoods);
}复制代码

上記の例では、最も高価な商品を見つける実証し、Collectors.maxBy()メソッドは、比較を渡し、我々は価格品に基づいて比較する必要が必要です。

同様に、最も安い商品を見つけるためには、単にmaxBy置き換えるminBy缶を。

partitioningBy

この方法は、partitioningByパーティションを表し、それは二つの部分に分けストリーム要素における条件に応じされ、これを地図に入れ、マップキーがブール型で、鍵記憶素子は、条件部を満たし真、偽の鍵が格納されている満たされていません要素条件。

{
    true -> 符合条件的元素
    false -> 不符合条件的元素
}复制代码

方法は、2つのオーバーロードされたメソッドpartitioningBy組成物で構成され

  • 過負荷1:partitioningBy(述語)
  • 重载2:partitioningBy(述語、コレクタ)

1 2オーバーロードされたヘビーデューティーを呼び出し、そのため最終的には2に過負荷をかける方法と呼ばれる、我々は重い負荷1の方法を見てください。

製品の種類の以下の実施例は、製品は、商品および非携帯電話の商品のカテゴリに分割されます。

@Data
@AllArgsConstructor
static class Goods {
    private String goodsName;
    // 类型,1:手机,2:电脑
    private int type;
    @Override
    public String toString() {
        return goodsName;
    }
}

public static void main(String[] args) {
    List<Goods> list = Arrays.asList(
            new Goods("iphoneX", 1)
            , new Goods("mate30 pro", 1)
            , new Goods("thinkpad T400", 2)
            , new Goods("macbook pro", 2)
            );
    
    // 手机归为一类,非手机商品归为一类
    // true -> 手机类商品
    // false -> 非手机类商品
    Map<Boolean, List<Goods>> goodsMap = list.stream()
        .collect(
            Collectors.partitioningBy(goods -> goods.getType() == 1)
        );
    // 获取手机类商品
    List<Goods> mobileGoods = goodsMap.get(true);
    System.out.println(mobileGoods);
}复制代码

あなたが保存する設定を使用したい場合は、2番目のパラメータpartitioningBy(述語、コレクタ)メソッドは、デフォルトのリスト・ストアで使用される一連の要素を指定するために使用することができ、書き込み:

Map<Boolean, Set<Goods>> goodsMap = list.stream()
    .collect(
        Collectors.partitioningBy(
            goods -> goods.getType() == 1
            // 指定收集类型
            , Collectors.toSet())
    );复制代码

ToListメソッド&toSet&toCollection

ToListメソッドtoSetと、より多く使用される二つの方法でストリームリスト、セット、コレクション、に要素を変換することができます。

Stream<Goods> stream = Stream.of(
        new Goods("iphoneX", 4000)
        , new Goods("mate30 pro", 5999)
        , new Goods("redmek20", 2999)
        );

List<Goods> list = stream.collect(Collectors.toList());
Set<Goods> set = stream.collect(Collectors.toSet());复制代码

デフォルトでは、ToListメソッドは、toSetはHashSetのを返し、ArrayListのを返しますが、このようなのLinkedListなど他の種類のコレクションを返したい場合は、あなたが使用することができtoCollection、それは開発者がどのようなニーズの独自のセットを指定することができます。

LinkedList<Goods> linkedList = stream.collect(Collectors.toCollection(LinkedList::new));复制代码

toConcurrentMap

ストリームtoConcurrentMapアプローチのConcurrentMapに変換することで、それが3つの過負荷で構成されています

  • 過負荷1:toConcurrentMap(Function keyMapper, Function valueMapper)
  • 過負荷2:toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction)
  • ヘビーデューティー3:toConcurrentMap(Function keyMapper, Function valueMapper, BinaryOperator mergeFunction, Supplier mapSupplier)

2過負荷発呼前記過負荷1、過負荷3は、2オーバーロードを呼び出し、最終的に実装された方法は、3つまでの過負荷します。

ヘビーデューティー1を見て、二つのパラメータ

  • keyMapper:ConcurrentMapがで指定されたキー値
  • valueMapper:指定されたキー値に対応します

次の例では、値の価格として、キーとして、製品の名前です。

List<Goods> list = Arrays.asList(
        new Goods("iphoneX", 4000)
        , new Goods("mate30 pro", 5999)
        , new Goods("redmek20", 2999)
);
ConcurrentMap<String, Integer> goodsMap = list.stream()
        .collect(
                Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice)
        );
System.out.println(goodsMap);复制代码

印刷:

{mate30 pro=5999, iphoneX=4000, redmek20=2999}复制代码

注:このメソッドは、キーが重複キーがある場合、重複するキーが存在する場合、それはIllegalStateExceptionが例外をスローします、繰り返すことはできません使用が必要です2をオーバーロードtoConcurrentMap(Function, Function, BinaryOperator)

そして、ヘビーデューティー2を見てください:toConcurrentMap(Function, Function, BinaryOperator)このメソッドの前に2つのパラメータをヘビーデューティー1を開発者が値の戻り値を選択することができ、キーの競合状況に対処するための3番目の引数として。

List<Goods> list = Arrays.asList(
        new Goods("iphoneX", 4000)
        , new Goods("mate30 pro", 5999)
        , new Goods("mate30 pro", 6000) // 这里有两个冲突了
        , new Goods("redmek20", 2999)
);
ConcurrentMap<String, Integer> goodsMap = list.stream()
        .collect(
                Collectors.toConcurrentMap(Goods::getGoodsName, Goods::getPrice, new BinaryOperator<Integer>() {
                    @Override
                    public Integer apply(Integer price1, Integer price2) {
                        // 选择价格贵的返回
                        return Math.max(price1, price2);
                    }
                })
        );
System.out.println(goodsMap);复制代码

印刷:{mate30 pro=6000, iphoneX=4000, redmek20=2999}

この例では、中にキーとしてプロの繰り返しをmate30 BinaryOperator我々はデータの一部リターンの高い価格を選びました、。

最後に、ヘビーデューティー2に比べて、3を過負荷に見える、パラメータの追加Supplier開発者が復帰一種類を指定することができ、ConcurrentMap

、2 3を過負荷にデフォルトで使用され、オーバーロードを呼び出しますConcurrentMap::new

注:4番目のパラメータのConcurrentMapかのConcurrentMapのサブクラスでなければなりません

セクション

この章のデータは説明Stream.collectの使用だけでなく、Collectorsクラスの静的メソッドを使用することを、次の記事では、我々は程度詳細に説明しますreduce関連する使用法。

技術を共有するために定期的にドライ品、一緒に学び、一緒に進行!マイクロチャンネル公共数:猿の下のコードをノック

おすすめ

転載: juejin.im/post/5dba7971518825698010f23c