コレクションツールクラスとコレクションのストリーミングプログラミング

コレクションツール

コレクション操作用のツールクラス静的メソッドが定義されています。

コレクションとコレクションの違いは何ですか?

コレクションは、コレクションフレームワークのトップレベルのインターフェイスであり、単一列コレクションの一般的なメソッドを定義します。一般的に使用される2つのサブインターフェースがあります。

  • リスト:すべての要素にインデックスが定義されています。整然とした。要素は繰り返すことができます。
  • セット:要素を繰り返さない。乱れた。
    コレクションは、コレクションフレームワークのツールクラスです。このクラスのメソッドはすべて、リストコレクションのソート、バイナリ検索、その他のメソッドなど、静的に提供されるメソッドです。>通常、一般的に使用されるコレクションはスレッドセーフではありません。効率を向上させるためです。
    複数のスレッドがこれらのコレクションを操作する場合、ツールクラスの同期メソッドを使用して、スレッドに対して安全でないコレクションを安全なコレクションに変換できます。

コレクションのメソッド

戻り値 方法 説明文
静的<T>ブール値 addAll(Collection <?super T> c、T ... elements) コレクションにデータをバッチで追加します。
静的<Tはオブジェクトと比較可能を拡張しますか?スーパーT >> T max(Collection <?extends T> coll) コレクション内の最大の要素を取得します。
静的<T> T max(Collection <?extends T> coll、Comparator <?super T> comp) コレクション内の最大の要素を取得します。
静的<Tはオブジェクトと比較可能を拡張しますか?スーパーT >> T min(Collection <?extends T> coll) コレクション内の最小の要素を取得します。
静的<T> T min(Collection <?extends T> coll、Comparator <?super T> comp) コレクション内の最小の要素を取得します。
静的ボイド シャッフル(List <?>リスト) コレクション内の要素をランダムに配置します。
静的ボイド swap(List <?>リスト、int i、int j) コレクション内の2つの要素を入れ替えます。
静的ボイド (リスト<?>リスト) コレクションの要素を逆にします。
static <T extends Comparable <?スーパーT >> void ソート(List <T>リスト) コレクションの要素を昇順で並べ替えます。
静的<T> void ソート(List <T>リスト、Comparator <?super T> c) コレクションの要素を昇順で並べ替えます。
静的<T>整数 binarySearch(List <?extends Comparable <?super T >> list、T key) 要素の添え字を検索するには、バイナリ検索を使用します。
静的<T>整数 binarySearch(List <?extends T> list、T key、Comparator <?super T> c) 要素の添え字を検索するには、バイナリ検索を使用します。
静的<T> void コピー(List <?super T> dest、List <?extends T> src) srcコレクションの要素をdestにコピーします。
静的<T> void fill(List <?super T> list、T obj) 指定した値をコレクションに入力します。
静的<T>コレクション<T> synchronizedCollection(Collection <T> c) スレッドセーフなコレクションを取得します。
静的<T>セット<T> synchronizedSet(Set <T> s) スレッドセーフなコレクションを取得します。
静的<T>リスト<T> synchronizedList(List <T>リスト) スレッドセーフなコレクションを取得します。
静的<K、V>マップ<K、V> synchronizedMap(Map <K、V> m) スレッドセーフなコレクションを取得します。

ストリーミングプログラミング

はじめに

ストリームはJava8の新機能です。また、Java8の新機能の中で最も学ぶ価値のある2つの新機能の1つでもあります。(もう1つはラムダ式です。)
ストリームはコレクション操作の拡張機能です。ストリームはコレクションの要素ではなく、データ構造でもありません。また、データストレージ自体の責任も負いません。ストリームはイテレータに似ており、コレクションの各要素を一方向にトラバースでき、循環的ではありません。
プログラムでは、Streamクラスを使用してストリームを記述できます。このクラスには、ストリーム内の要素に対してさまざまな処理と操作を実行するためのいくつかのメソッドがあります。一部の操作はストリームオブジェクト自体を取得できますが、現時点では、このストリームオブジェクトを他の処理に引き続き使用できます。

コレクションにストリーミングプログラミングを使用する理由

  • コレクション内の要素を操作するときに、他の操作の結果を使用する必要がある場合があります。このプロセスでは、ストリーミングプログラミングのコレクションにより、コード量を大幅に簡略化できます。データソースからストリームにデータを読み取り、ストリーム内のデータに対してさまざまな操作(削除、フィルター、マップなど)を実行できます。各操作結果もストリームオブジェクトであり、これを使用できます他のデータ処理のためにオブジェクトをストリームします。

コレクションストリーミングプログラミングを使用する手順

  • 通常の状況では、ストリーミングプログラミングを使用してコレクション内のデータを処理するには、次の3つの手順が必要です。
  1. データソースを取得し、データソースからストリームにデータを読み取ります。
  2. ストリーム内のデータに対してさまざまな処理を実行します。
  3. ストリーム内のデータを統合します。
    ステップ2では、ストリーム内のデータに対してさまざまな処理を実行できるいくつかの方法があります。これらのメソッドはストリームオブジェクト自体を返します。このストリームオブジェクトを他のデータ処理に引き続き使用できます。このような操作は中間操作と呼ばれます
    ステップ3では、ストリーム内のデータを集計および分析して、ストリームを閉じる方法がいくつかあります。現時点では、ストリーム内のデータに対して他の処理を実行することはできません。このような操作は最終操作と呼ばれ
    、中間操作と最終操作では、基本的にすべてのメソッドパラメータは関数型インターフェイスです。コレクションを使用してコードの量を簡略化するストリーミングプログラミングには、ラムダ式の熟練が必要です。

データソースの取得

名前が示すように、データソースはストリーム内のデータのソースです。これは、データソースからストリームにデータを読み込んで処理するコレクションストリーミングプログラミングの最初のステップです。ほとんどの場合、データソースはコレクションコレクションから取得されます。場合によっては、アレイから取得されることもあります。
注:
コレクションストリーミングプログラミング最初のステップは、データソースからストリームにデータを読み込むことです。このとき、ストリーム内のデータは、データソース内のデータに関係なく処理されます。つまり、すべての中間操作はストリーム内のデータに対して何らかの処理を実行でき、これらの処理はデータソース内のデータに影響を与えません。実際、コレクションストリーミングプログラミングを使用すると、より多くのクエリ操作が実行され、コレクション内のデータは変更されません。

データソースからストリームにデータを読み取る

これは、コレクションストリーミングプログラミングの最初のステップであり、コンテナーからストリームにデータを読み取ります。データソースとして使用されるコンテナーに関係なく、ストリームに読み込まれたメソッドの戻り値はStreamでなければなりません

import java.util.*;

import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();//获取的是串行流
        Stream<Integer> stream2 = collection.parallelStream();//获取的是并行流

        //1、数组作为数据源
        Integer[]array=new Integer[]{1,2,3,4,5,6,7,8,9,0};
        //2、将数组作为数据源读入流中
        Stream<Integer> stream3=Arrays.stream(array);int[] array1 = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
        // 截取数组中的一部分数据,读取到流中
        IntStream stream4 = Arrays.stream(array1, 3, 8);
        

    }
}

最終操作

最終操作の紹介

最後の操作では、ストリーム内のデータを集約してコレクションに格納するか、ストリーム内のデータを直接トラバースして、データ統計、分析... 最後の操作を通じて、ストリーム内のデータから必要な情報を取得できます。
注意が必要な事項
これらのメソッドがストリームオブジェクト自体を返さないためだけではなく、最終操作は最終操作と呼ばれます。最も重要な理由は、すべての最終操作がストリームを閉じることです。ストリームが閉じられると、ストリーム内のすべてのデータが破棄されます。あなたはストリームがクローズされている使用している場合は、そこになりますjava.lang.IllegalStateException例外。

集める

ストリーム内のデータをまとめて集計し、データに対して何らかの処理を行います。最も一般的な処理は、ストリーム内のデータをコレクションに格納することです。

このメソッドでは、パラメーターはコレクターです。コレクターはインターフェースであり、このインターフェースはまだ機能的なインターフェースではありません。このインターフェースを実装すると、データ収集のルールをカスタマイズできます。しかし、ほとんどの場合、このインターフェースを手動で実装するべきではありません。コレクターツールクラスを使用するだけです。

<R,A> R collect(Collector<? super T,A,R> collector)


import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
        //List<Integer>list=stream1.collect(Collectors.toList());
        //list.forEach(System.out::println);
        
//        Set<Integer>set=stream1.collect(Collectors.toSet());
//        set.forEach(System.out::println);
        Map<String,String> map= stream1.collect(Collectors.toMap(e->"key"+e,e->"value"+e));
        map.forEach((k,v)->{
            System.out.println("key = " + k + ", value = " + v);
        });
    }
}

減らす

ストリーム内のデータは、特定のルールに従って計算および処理されます。
reduceメソッドの結果はOptionalであり、null許容データを表します。実際のデータを取得する場合は、getメソッドを使用して取得する必要があります。

import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
       //reduce方法得到的结果是Optional,表示可空数据。如果要获取实际的数据,需要用get方法获取。
        //stream1.reduce((a,b)->a+b);
        Optional<Integer> reduce = stream1.reduce(Integer::sum);
        Integer sum=reduce.get();
        System.out.println(sum);
    }
}

カウント

ストリーム内のデータ量をカウントするために使用されます。

import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
        //注意返回值类型
       long count=stream1.count();
        System.out.println(count);
    }
}

forEach

これは、ストリーム内のデータを反復およびトラバースするために使用されます。メソッドのパラメーターは、機能インターフェース、Consumerです。次に、ストリーム内のデータをConsumerインターフェースメソッドのパラメーターに取り込み、メソッド本体内のストリーム内のデータを繰り返し処理します。CollectionインターフェースのforEachメソッドに似ています。

最大および最小

これらは、ストリーム内のデータの最大値と最小値を取得するために使用される2つの最終操作メソッドです。maxメソッドとminメソッドのパラメーターはコンパレータインターフェースです。

import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
       int min=stream1.min(Integer::compareTo).get();
       int max=stream1.max(Integer::compareTo).get();
        System.out.println(min+","+max);
    }
}

マッチング

マッチング操作はメソッドではなく、マッチングに使用されるいくつかのメソッドの総称です。

  • allMatch(述語):ストリーム内のすべてのデータがパラメーター条件を満たす場合のみ、trueを返します。
  • anyMatch(述語):ストリームにデータがあり、パラメーター条件が満たされている限り、trueを返します。
  • noneMatch(述語):ストリーム内のすべてのデータがパラメーター条件を満たさない場合にのみtrueを返します。
import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
        // 验证,是否流中所有的数据都满足指定条件
        // boolean ret = stream1.allMatch(ele -> ele > 0);
        // System.out.println(ret);

        // 验证,是否流中有满足条件的数据
        // boolean ret = stream1.anyMatch(ele -> ele > 5);
        // System.out.println(ret);

        // 验证,是否流中所有的数据都不满足指定的条件
        boolean ret = stream1.noneMatch(ele -> ele > 15);
        System.out.println(ret);
    }
}

見つける

ストリームからデータの一部を見つけます。

  • findFirst():ストリームから要素を取得します。(一般的に、取得の最初の要素です)
  • findAny():ストリームから要素を取得します。(一般的に、取得の最初の要素です)

同期フローでは、これら2つの方法に違いはありません。最初の要素が取得されます。ただし、並列ストリームでは、findAnyメソッドとfindメソッドによって返される結果が異なる場合があります。


import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        //1、Collection集合作为数据源
        Collection<Integer> collection=new ArrayList<>();
        Collections.addAll(collection,1,2,3,4,5,6,7,8,9,0);
        //2、将Collection作为数据源读入到流中
        Stream<Integer> stream1=collection.stream();
        //findFirst
        System.out.println(collection.stream().findFirst().get());
        System.out.println(collection.parallelStream().findFirst().get());
        System.out.println();
        //findAny
        System.out.println(collection.stream().findAny().get());
        System.out.println(collection.parallelStream().findAny().get());
    }
}

IntStreamの最後の操作

IntStreamも、Streamクラスに似たストリームオブジェクトであり、Streamクラスとは少し異なります。ストリーム内のデータであるIntStreamは、すべてint型のデータです。
IntStreamは、Streamと比較して、ほとんどのメソッドがまったく同じです。上記の最終操作に加えて、いくつかの追加メソッドがあります。

import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        // 1. 实例化一个int[],作为数据源
        int[] array = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
        // 2. 获取到一个IntStream
        IntStream stream = Arrays.stream(array);

        // int max = stream.max().getAsInt();                   // 获取最大值
        // int min = stream.min().getAsInt();                   // 获取最小值
        // int sum = stream.sum();                              // 获取流中所有的数据的和
        // long count = stream.count();                         // 获取流中有多少数据
        // double asDouble = stream.average().getAsDouble();    // 计算流中所有的数据的平均值

        // 获取对流中数据的统计分析结果,包含了(最大值、最小值、和、平均值、数量)
        IntSummaryStatistics intSummaryStatistics = stream.summaryStatistics();
        System.out.println(intSummaryStatistics.getMax());      // 获取最大值
        System.out.println(intSummaryStatistics.getMin());      // 获取最小值
        System.out.println(intSummaryStatistics.getSum());      // 获取和
        System.out.println(intSummaryStatistics.getAverage());  // 获取平均值
        System.out.println(intSummaryStatistics.getCount());    // 获取数量
         }
}

最後の操作はストリームを閉じます。閉じたストリームを使用すると、例外が発生します!

スレッド「メイン」の例外java.lang.IllegalStateException:ストリームはすでに操作されているか、閉じられています

中間操作

データソースからストリームにデータを読み取り、ストリーム内のデータに対してさまざまな処理を実行します。ストリーム内のデータを処理するこれらのメソッド。各メソッドの戻り値はストリームオブジェクト自体です。この戻り値を直接使用し、他のメソッドを呼び出してデータに対して他の処理を実行できます。このプロセスは、最後の操作まで続行できます。

フィルタ

条件付きフィルタリング、**ストリーム内の条件を満たすデータを保持し、条件を満たさないデータを削除します。**

// 将流中所有的年龄大于10岁的数据保留
list.stream().filter(ele -> ele.getAge() > 10).forEach(System.out::println);

明確な

ストリーム内の要素の重複排除、重複排除。このメソッドにはパラメーターがありません。重複排除ルールはHashSetと同じです。

  • 2つのオブジェクトのhashCode()を比較する
  • hashCodeが同じ場合は、equals()を比較します

並べ替え

特定のルールに従ってストリーム内のデータを並べ替えます。

  • Sorted():ストリームの要素に対応するクラスに従って、サイズ比較のためのComparableインターフェースを実装し、昇順でソートします。
  • 並べ替え(コンパレータ):パラメータインターフェースによって提供されるサイズ比較ルールに従って、要素のサイズを比較し、昇順で並べ替えます。

限定

ストリーム内の指定された数の要素を制限、遮断します。0番目のビットからの傍受。

スキップ

スキップ、ストリーム内の指定された数の要素をスキップします。

MapToInt

ストリーム内のデータを、データのタイプに関係なく、intデータに置き換えます。このとき、メソッドが取得する戻り値の型はIntStreamです。

地図

これはマッピング関係です。このメソッドを使用して、ストリーム内のデータをマッピングし、元のデータを新しいデータで置き換えることができます。

import java.util.*;

import java.util.stream.Collectors;
import java.util.stream.IntStream;
import java.util.stream.Stream;


public class Test {
    public static void main(String[] args) {
        // 1. 获取数据源
        List<Person> list = getDataSource();
        //注:以下每次调用都使用了最终操作foeEach
        // 2. 中间操作filter
        // list.stream().filter(ele -> ele.getAge() > 10).forEach(System.out::println);

        // 3. 中间操作distinct
        // list.stream().distinct().forEach(System.out::println);

        // 4. 中间操作sorted
        //无参sorted使用类继承Comparable时实现的compareTo方法
        //list.stream().sorted().forEach(System.out::println);
        //有参sorted使用lambda表达式来指定排序方式
        // list.stream().sorted((p1, p2) -> p1.getHeight() - p2.getHeight()).forEach(System.out::println);

        // 5. 中间操作limit
        // list.stream().limit(5).forEach(System.out::println);
        // 需求: 获取身高前5名
        // list.stream().sorted((p1, p2) -> p2.getHeight() - p1.getHeight())
        //              .limit(5)
        //              .forEach(System.out::println);

        // 6. 中间操作skip
        // 需求:截取身高的 [4,7] 名
        // list.stream().sorted((p1, p2) -> p2.getHeight() - p1.getHeight())
        //         .limit(7)
        //         .skip(3)
        //         .forEach(System.out::println);

        // 7. 中间操作map
        // 需求:将一个存储了所有的Person对象的集合,将所有的名字提取出来,单独存放到一个集合中。
        // List<String> names = list.stream().map(Person::getName).collect(Collectors.toList());

        // 8. mapToInt
        // 计算一个存储了所有的Person对象的流中的年龄平均值。
        double asDouble = list.stream().mapToInt(Person::getAge).average().getAsDouble();
        System.out.println(asDouble);

    }

    /**
     * 获取数据源
     * @return 存储了若干个Person对象的数据源
     */
    private static List<Person> getDataSource() {
        List<Person> list = new ArrayList<>();
        Collections.addAll(list,
                new Person("Han Meimei", 11, 165, 45),
                new Person("Li Lei", 12, 168, 51),
                new Person("Lucy", 12, 166, 50),
                new Person("Lily", 12, 166, 49),
                new Person("Polly", 3, 92, 22),
                new Person("Tom", 13, 162, 52),
                new Person("Jerry", 2, 88, 18),
                new Person("Lin Tao", 11, 162, 53),
                new Person("Jim", 14, 167, 51),
                new Person("Jim", 14, 167, 51)
        );
        return list;
    }
}

class Person implements Comparable<Person> {
    private String name;
    private int age;
    private int height;
    private int weight;

    public Person(String name, int age, int height, int weight) {
        this.name = name;
        this.age = age;
        this.height = height;
        this.weight = weight;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public int getHeight() {
        return height;
    }

    public void setHeight(int height) {
        this.height = height;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }


    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Person person = (Person) o;
        return age == person.age &&
                height == person.height &&
                weight == person.weight &&
                Objects.equals(name, person.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age, height, weight);
    }

    @Override
    public String toString() {
        return "Person{" +
                "name='" + name + '\'' +
                ", age=" + age +
                ", height=" + height +
                ", weight=" + weight +
                '}';
    }

    @Override
    public int compareTo(Person o) {
        return this.age - o.age;
    }
}

flatMap

マップと同様に、flatMapはフラットマップです。

public class FMap {
    public static void main(String[] args) {
        String[] strs = {"hello", "world"};

        // 需求:输出每一个组成字符串的字符
        // 直接映射,将流中的元素(字符串),替换成了toCharArray之后的结果(字符数组)
        // 映射完成后,流中的数据依然是两个,分别是两个字符数组
        Arrays.stream(strs).map(String::toCharArray).forEach(ele -> System.out.println(Arrays.toString(ele)));

        // 常用于map直接映射完成后,流中的数据是一个个的容器,而我们需要对容器中的数据进行处理。
        // 此时,可以使用扁平化的映射,将容器中的元素直接存储于一个流中。
        Arrays.stream(strs).map(str -> str.split(""))
                .flatMap(Arrays::stream)
                .distinct()
                .forEach(System.out::println);
    }
}

おすすめ

転載: www.cnblogs.com/dch-21/p/12757817.html