流れ方1編


流れ方1編


ストリームとコレクションは、連続要素のフォーマット値を格納するためのデータ構造インタフェースを提供します.
コレクションの場合、すべての要素は事前に計算され、ストリームはリクエスト時にのみ要素を計算します.
また、コレクションは開発者が外部反復サブモードを使用し、ストリームは内部反復サブモードを使用する必要があります.
外部繰返しとは,開発者が直接集合中の要素をコードとして繰り返しインポートするコードパターンである.Indexを使用するfor文とIvalterrを使用するwhile文は、外部反復文字を使用します.逆に、内部リピータはコレクション内で要素を繰り返し、開発者は各要素が処理するコードのコードモードのみを提供します.下図を見ればわかります.

外部反復と内部反復イメージ



内部反復器を使用する利点は、アセンブリ内で要素を繰り返して配置する方法であり、開発者は要素処理コードに集中するだけです.内部リピータは、要素のリピータ順序を変更したり、要素を割り当ててマルチコアCPUを最大限に利用して並列処理を行うことで、個々の処理の順序よりも外部リピータの方が効率的に要素をリピータすることができます.

1.並列処理とは?


パラレル処理とは、1つのタスクをサブタスクに分割し、分離したスレッドでサブタスクをパラレル処理することです.パラレル処理フローは、実行時にタスクを自動的にサブタスクに分割し、サブタスクの結果を自動的にマージして最終成果物を生成します.たとえば、集合要素の合計を求める場合、シーケンス処理フローは1つのスレッドから要素を1つずつ読み出して合計され、パラレル処理フローは複数のスレッドの一部から要素を結合し、最終的にこれらの部分を結合して連結全体を生成します.
次のコードは、シーケンス処理フローとパラレル処理フローを使用する場合、コンソールが使用するスレッド名を出力する例です.実行結果によると、パラレル処理フローには、メインスレッドを含むForkJoinPool(스레드 풀)個の作業スレッドのパラレル処理要素が表示されます.
//병렬처리
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class ParallelExample {

    public static void main(String[] args) {
        List<String> list = Arrays.asList(
                "홍길동", "신용권", "김자바"
                ,"람다식","박병렬"
        );
        // 순차 처리
        Stream<String> stream = list.stream();
        stream.forEach(ParallelExample :: print);
        System.out.println();

        // 병렬 처리
        Stream<String> parallelStream = list.parallelStream();
        parallelStream.forEach(ParallelExample::print);

    }

    private static void print(String str) {
        System.out.println(str + " : " + Thread.currentThread().getName());
    }
}

実行結果



ストリームは、中間処理および最終処理を行うことができる。


ストリームは、コレクション要素に対して中間処理と最終処理を実行し、中間処理はマッピング、フィルタリング、ソートを実行し、最終処理は重複、カウント、平均、要約などの集約を実行します.
処理を実行します.
次の例では、リストに格納されているStudioオブジェクトを中間処理からscoreフィールド値にマッピングし、最終処理でscore平均値を計算します.
import java.util.Arrays;
import java.util.List;

public class MapAndReduceExample {
    public static void main(String[] args) {

        List<Student> students = Arrays.asList(
                new Student("임준영",100),
                new Student("배성탑",90),
                new Student("임광빈",80),
                new Student("양아름",75)
        );

        double avg = students.stream()
                .mapToInt(Student::getScore) // 중간처리(학생 객체를 점수로 매핑)
                .average()
                .getAsDouble();

        System.out.println("평균 점수: " + avg);
    }
}

2.ストリームのタイプ


Java 8から新しく追加されたjavaを開始します.util.ストリーミングパッケージには、ストリーミングAPIが含まれています.パッケージの内容から,BaseStreamインタフェースは親インタフェースであり,そのサブインタフェースは次の画像のように継承関係を持つ.

BaseStreamインタフェースは、すべてのストリームに使用できる汎用メソッドを定義しますが、コードには直接使用しません.サブストリームInStream、IntStream、
LongStreamとDoubleStreamは直接使用されるストリームであり、Streamはオブジェクト要素を処理するストリームであり、InStream、LongStream、DoubleStreamはそれぞれデフォルトタイプのint、long、double要素を処理します.このストリームインタフェースのインプリメンテーションオブジェクトは、異なるソースから取得できます.主にコレクションと配列から取得されますが、次のソースからストリーム実装オブジェクトを取得することもできます.
タイプメソッド(パラメータ)ソースStream<T>javaを返します.util.Collection.stream(), java.util.Collection.パラレルStream()集合InteStreamInteStream.range(int, int), IntStream.rangeClosed(int,int)int範囲LongStreamLongStream.range(long, long), LongStream.長距離クローズ長範囲Stream<String>ファイル.lines(Path, Charset), BufferedReader.Lines()Collection Stream<T>、InteStream、LongStream、DoubleStreamArrays.stream(T[]), Arrays.stream(int[]), Arrays.stream(long[]), Arrays.stream(double[]), Stream.of(T[]), IntStream.of(int[]), LongStream.of(long[]), DoubleStream.of(double[])アレイDoubleStream、IntStream、LongStream Random.doubles(...), Random.ints(), Random.long()乱数Stream<Path>ファイル.find(Path, int , BiPredicate, FileVisitOption), Files.List(Path)ディレクトリ

3.コレクションからストリームを取得


次の例では、リストセットからStreamを取得し、要素をコンソールに出力します.
import java.util.Arrays;
import java.util.List;

public class FromCollectionExample {
    public static void main(String[] args) {

        List<Student> students = Arrays.asList(
                new Student("임준영",100),
                new Student("배성탑",90),
                new Student("임광빈",80)
        );

        students.forEach(s -> System.out.println(s.getName()));
    }
}

package stream;
  
public class Student {

    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public int getScore() {
        return score;
    }

}

数値範囲からストリームを取得


以下のサンプルコードはInStreamのRangeClosed()メソッドを用いて1から100の和を求める.rangeClosed()は、1番目のパラメータから2番目のパラメータまで順次提供されるInstreamを返します.IntStreamの別のrange()メソッドも同じIntStreamを返しますが、2番目のパラメータ値は含まれません.
import java.util.stream.IntStream;

public class FromIntRangeExample {

    public static int sum;

    public static void main(String[] args) {
        IntStream intStream = IntStream.rangeClosed(1,100);
        intStream.forEach(a -> sum += a);
        System.out.println("총합 :" +  sum);
    }
}

ファイルからストリームを取得


次のコード例は、ファイル内の静的メソッド行()およびBufferedReaderの行()メソッドを使用して、テキストファイルの内容を動作単位で読み取り、コンソールに出力します.
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FromFileContentExample {

    public static void main(String[] args) throws IOException {

        // 파일의 경로 정보를 가지고 있는 Path 객체 생성
        Path path = Paths.get("/Users/limjun-young/workspace/privacy/linedata.txt");
        Stream<String> stream;

        //Files.Line() 메소드 이용
        stream = Files.lines(path, Charset.defaultCharset());
        stream.forEach(System.out :: println);
        System.out.println();

        //BufferedReader의 lines() 메소드 이용
        File file = path.toFile();
        FileReader fileReader = new FileReader(file);
        BufferedReader bufferedReader = new BufferedReader(fileReader);
        stream = bufferedReader.lines();
        stream.forEach(System.out :: println);

    }

}

実行結果



ディレクトリからストリームを取得

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public class FromDirectoryExample {
    public static void main(String[] args) throws IOException {
        Path path = Paths.get("/Users/limjun-young/workspace/privacy");
        Stream<Path> stream = Files.list(path);
        stream.forEach(p -> System.out.println(p.getFileName()));
        
    }
}

実行結果



4.パイプライン


大量のデータの加工と縮小は、通常、レプリケーションと呼ばれます.データの合計、平均、カウント、最大値、最小値は、典型的な結果です.ただし、コレクション内の要素が直接レプリケーションの結果として統計できない場合は、統計を容易にするために、フィルタ、マッピング、ソート、パケットなどの中間処理が必要です.

中間ストリームを作成すると、要素が直ちに中間処理(フィルタ、マッピング、ソート)を行うのではなく、最終処理が開始されるまで中間処理が遅延します.最終処理が開始されると、集合要素は最終処理まで中間ストリームで処理されます.
Streamインタフェースには、フィルタリング、マッピング、ソートなどの多くの中間処理方法があります.これらのメソッドは、中間処理のストリームを返します.その後、ストリームは再び中間処理方法を呼び出してパイプラインを形成する.たとえば、メンバーセット内の男性の中間ストリームのみをフィルタリングして接続し、男性の年齢にマッピングされたストリームを接続し、最終男性の平均年齢を統計すると、下図に示すようにパイプラインが形成されます.
// 스트림 파이프 라인
import java.util.Arrays;
import java.util.List;

public class StreamPipelinesExample {

    public static void main(String[] args) {
        List<Member> members = Arrays.asList(
                new Member("홍길동", Member.MALE, 30),
                new Member("김나리", Member.FEMALE, 20),
                new Member("신용권", Member.MALE, 45),
                new Member("박수미", Member.FEMALE, 27)
        );

        double ageAvg = members.stream()  
                .filter(m -> m.getSex() == Member.MALE) 
                .mapToInt(Member::getAge)
                .average()
                .getAsDouble();

        System.out.println("남자 평균 나이: " + ageAvg);
    }
}


// 회원 클래스
public class Member {

    public static int MALE = 0;
    public static int FEMALE = 1;

    private String name;
    private int sex;
    private int age;

    public Member(String name, int sex, int age) {
        this.name = name;
        this.sex = sex;
        this.age = age;
    }

    public int getSex() {
        return sex;
    }

    public int getAge() {
        return age;
    }
}
double ageAvg = members.stream() <- 오리지날 스트림
 .filter(m -> m.getSex() == Member.MALE)  <- 중간 처리 스트림
               .mapToInt(Member::getAge)  <- 중간 처리 스트림
               .average()
               .getAsDouble();            <- 최종 처리 
filter(m -> m.getSex() == Member.MALE)は、男性メンバーオブジェクトを要素とする新しいストリームを作成します.mapToInte(メンバー::getAgent()メンバーオブジェクトを年齢値にマッピングし、年齢要素の新しいストリームを作成します.AVerage()メソッドは、age要素の平均値をOptionalDubleに格納します.OptionalDoubleから格納されている平均値を読み込むには、getAsDouble()メソッドを呼び出します.
中間処理方法と最終処理方法は、리턴 타입によって容易に区別することができる.리턴 타입이 스트림이면 중간 처리 메소드이고, 기본 타입이거나 OptionalXXX라면 최종 처리 메소드 입니다.が属するインタフェースの共通の意味は、Stream、InteStream、LongStream、DoubleStreamです.

5.フィルタ(distinct)、フィルタ()


フィルタリングは、要素をフィルタリングするための中間処理機能です.フィルタリング方法distint()およびfilter()は、すべてのストリームが有する汎用的な方法である.distinct()の方法は重複データを除去することができ、StreamはObjectである.「equals」(Object)がtrueの場合、同じオブジェクトとして扱われ、重複が解消されます.IntStream、LongStream、DoubleStreamの値が同じであれば、冗長性を排除できます.
次の例では、名前リストから重複する名前を削除して出力します.そして「神」という名前だけをフィルタリングして出力します.
import java.util.Arrays;
import java.util.List;

public class FilteringExample {

    public static void main(String[] args) {
        List<String> names = Arrays.asList(
                "홍길동", "신용권", "김자바", "신용권", "신민철"
        );

        names.stream()
                .distinct()
                .filter(s -> s.startsWith("신"))
                .forEach(System.out::println);
    }

}

6.マッピング(FlatMapXXX()、mapXXX()、asXXXXXStream()、boxed()


マッピングは、ストリーム内の要素を中間処理機能で置き換える操作です.
ストリームが提供するマッピング方法には、flatXXX()、mapXXX()およびasDoubleStream()、asLongStream()およびboxed()が含まれる.

FlatMapXXX()メソッド


FlatMapXXX()メソッドは、複数の要素からなる新しいストリームを返します.これらの要素は置き換えられます.

次の例では、入力されたデータがリストに格納され、要素別に単語が抽出され、単語ストリームとして再生成されると仮定する.入力したデータが数値である場合、数値を抽出し、数値ストリームを再生成します.
import java.util.Arrays;
import java.util.List;

public class FlatMapExample {
    public static void main(String[] args) {
        List<String> inputList1 = Arrays.asList("java8 lamda", "stream mapping");


        inputList1.stream()
                  .flatMap(data -> Arrays.stream(data.split(" ")))
                  .forEach(System.out :: println);


        List<String> inputList2 = Arrays.asList("10, 20, 30", "40, 50, 60");

        inputList2.stream()
                  .flatMapToInt(data -> {
                      String[] strArr = data.split(",");
                      int[] intArr = new int[strArr.length];
                      for (int i = 0; i < strArr.length; i++) {
                          intArr[i] = Integer.parseInt(strArr[i].trim());
                      }
                      return Arrays.stream(intArr);
                  }).forEach(number -> System.out.println(number));
    }
    
}
次は次の2つの流れ方を参考にしてください.
流れ方2編
参考文献:Javaです