LambDASを用いたJavaにおける簡単なコレクション操作


Java 8で導入された最も強力な機能の1つは、最初にそれがあまり見えないかもしれないけれども、ラムダでした、新しい機能は多くの場合、コード化と実行を速くします、正しく使用されるならば.ここでは、Javaでのストリームとラムダ式のパワーを調べ、それらを使用してコレクションを操作します.これは、高度なチュートリアルではなく、この機能への導入です.うまくいけば、いくつかの新しい情報は、最後に到達する時間で共有されます.

初期クラス
我々は、彼らの名前、年齢といくつかの等級を格納する学生のための単純なクラスから始めます.これは、後の例で我々を助けます.
public class Student {
    private String name;
    private double gradeAtMath;
    private double gradeAtEnglish;
    private int age;
    public boolean passed() {
        return (gradeAtMath + gradeAtEnglish) / 2 >= 5;
    }
    // Getters and Setters
}

ストリームJavaでのfilter ()
何か小さくて簡単に始めましょう.私たちにはコレクション(この例でリストがあります、しかし、それはどんなJavaコレクションでもありえます)は、学生を大学に格納します.さて、私たちは名前“m”で始まる名前を抽出したいです
List<Body> filtered= students.stream()
        .filter(s -> s.getName().toUpperCase(Locale.ROOT).startsWith("M"))
        .collect(Collectors.toList());
これを壊しましょう.まず、我々のコレクションからストリームを作成します.次に、filter ()を使用して、ラムダ式を提供し、生徒の名前を取得し、大文字を作り、"m "から始まるかどうかを調べます.最後に、新しいリストで結果を収集します.
最初に、より多くの伝統的な方法を使用して同じ効果を達成することができますので、最初に、それは多くのように見えないかもしれませんが、我々はちょうど始まっているばかりです.大きなファジーステートメントを記述する必要なしに、より複雑な演算を行うために、複数のフィルタを連鎖できます.
List<Student> filtered = students.stream()
        .filter(s -> s.getName().toUpperCase(Locale.ROOT).startsWith("M"))
        .filter(s -> s.getGradeAtMath() >= 5)
        .filter(s -> s.getGradeAtEnglish() < 5)
        .filter(Student::passed)
        .collect(Collectors.toList());
ここで我々はチェーンの複数のフィルタは、我々が探している正確な結果を得るために.興味深い例として、最後のフィルタがあります.ここでは、利息の値を返すメソッドを指定する必要があります.

複数のfilter ()呼び出しは、実行時間が長くなりますか?
これは何度も質問され、一見して、複数のfilter ()コールを行うことは効率的ではないようです.しかしこれは必ずしもそうではない.使用する述語によっては、コンパイラやJVMによって行われる最適化を行うことができます.これにより、同じ実行時間またはより良い実行時間が得られます.これは、ストリームに対してfilter ()を2回呼び出すと、最初の呼び出しが結果として得られたコレクションの最初のコレクションと2番目の値で実行されないことを意味します.ストリームには、中間および端末操作を持つ複数のパイプラインがあります.パイプラインの端末動作が実行されるまで、パイプラインソースの横断は開始されない.
より高速な実行を保証するために1つの最適化を行うには、ラムダ式の代わりにメソッドリファレンスを使用することです.我々が使うならば.filter(学生::渡される)は、作成されているより少ないオブジェクトをyieldします.filter ( s -> s paspath () )結果として実行時間が速くなります.
ほとんどの場合、複雑な述語と複数のフィルタ呼び出しの連鎖の間の実行時間差は、単純な述語を持つそれぞれが無視できます.私の推薦は読みやすく理解しやすい方に行くことです.

ストリームsort ()
別の便利な関数は、コレクションをソートすることです.これはsort ()メソッドを使用して実現されます.filter ()と同じように、ラムダ式を使って簡単にできます.以下は、学生名をソートします.両方の例は同じことをしますが、私はそれらの両方を提供し、どのようにラムダとコンパレータを使用してクリーンなコードを実現することができます.
List<Student> sorted = students.stream()
        .sorted((s1, s2) -> s1.getName().compareTo(s2.getName()))
        .collect(Collectors.toList());
List<Students> sorted= students.stream()
        .sorted(Comparator.comparing(Student::getName))
        .collect(Collectors.toList());
番目の例では、getName ()メソッドの戻り値を比較する比較器を提供します.
ソーティング機能のパワーは、コンパレータークラスにあります.学生が同じ名前を持っているのは珍しいことではないので、名前で並べ替えをするとき、同じ名前で他の前に数学で最高学年を持つ人が欲しいと仮定しましょう.より伝統的なメカニズムでは、我々はより多くの基準を持ちたいならば、これは非常に複雑な仕事であるでしょう.Java 8では、コンパレータのパワーで、これは複数の比較器を連鎖させ、結果として1をsort ()関数に適用することで簡単に実現できます.| NAME | Grade at math | Grade at English | Age |+------+---------------+------------------+------+|Tom | 8 | 7 | 3 ||Jerry | 9 | 5 | 2 ||Spike | 7 | 9 | 4 ||Tom | 7 | 7 | 3 |とコード
List<Students> students = getAllStudents();
Comparator<Student> comparator = Comparator.comparing(Student::getName)
        .thenComparing(Student::getGradeAtMath);
students.stream().sorted(comparator);
出力:| NAME | Grade at math | Grade at English | Age |+------+---------------+------------------+------+|Jerry | 9 | 5 | 2 ||Spike | 7 | 9 | 4 ||Tom | 8 | 7 | 3 ||Tom | 7 | 7 | 3 |この関数は必要に応じて多くの呼び出しを行うことができます.実際のシナリオでは、多くのデータを持っているので、いくつかのフィールドに対して同じ値を持つ2つ以上のエントリのチャンスが増加する.連鎖比較器は、そのような衝突が存在するとき、我々が正確な順序を持つのを許します.
この記事はもともと私のウェブサイトに掲載されました.より詳細な情報と例をJava Streams and Collection Manipulationにあります.