JavaRush /Java Blog /Random-JA /Java 8 でのループの除去
KapChook
レベル 19
Volga

Java 8 でのループの除去

Random-JA グループに公開済み
Java 8 で導入された関数型スタイルは、言語への優れた追加です。現在、Java は純粋な OOP ではなく、OOP と関数型プログラミングのハイブリッドになっています。これはゲームチェンジャーであり、これらの変化を吸収するにはOOPの脳を変える必要があります。 Java 8 でのループの除去 - 1しかし、なぜこれらの変化を受け入れなければならないのでしょうか? 純粋な OOP を使用して問題を解決できるのに、なぜ関数型スタイルに慣れようとして時間を無駄にする必要があるのでしょうか?
  • Java 8 で導入された関数型スタイルは、ビジネス ロジックとコードの間のギャップを減らすのに役立ちます。より高いレベルで自然な流れでストーリーを伝えることができます。どうしたいかを言う代わりに、何をしたいかを言うことができます。

  • コードはよりクリーンかつ簡潔になります。

  • 高次関数を使用すると、次のことが可能になります。

    • 関数を他の関数に送信する
    • 他の関数の中に関数を作成する
    • 他の関数から関数を返す

    これは Java にとって大きな利点です。Java では、これを行うためにオブジェクトを送信、作成、返す必要があります。より信頼性が高く、焦点を絞った、再利用しやすいコードを作成できるようになります。

  • ラムダのおかげで、遅延計算を行うことができます。ラムダ式がメソッドの引数として送信されると、コンパイラはメソッド内で呼び出されたときにラムダ式を評価します。これは、すぐに評価される通常のメソッド引数とは異なります。

  • Lambda を使用すると、単体テストの作成が楽しくなります。これらを使用すると、クリーンでサイズが小さく、すばやく作成できる軽量のテストを作成できます。ラムダを使用してテスト対象のコードをルートアウトできます。これにより、あらゆる種類のシナリオがコードにどのような影響を与えるかをテストできます。

  • 学ぶべき新しいパターン。

  • さらにもっと!

しかし、水は十分です。この記事では、従来のサイクルに代わる解決策を見ていきます。もちろん、サイクルは柔軟ですが、それには代償が伴います。break、ループの動作が劇的に変化し、コードが何を達成しようとしているのかを理解するだけでcontinueなく、returnループがどのように機能するのかも理解する必要があります。次に、ループをより簡潔で読みやすいコードに変換する方法を見ていきます。

コーディングを始めましょう!

記事を使って作業していきます。記事にはタイトル、著者、およびいくつかのタグがあります。
private class Article {

    private final String title;
    private final String author;
    private final List<String> tags;

    private Article(String title, String author, List<String> tags) {
        this.title = title;
        this.author = author;
        this.tags = tags;
    }

    public String getTitle() {
        return title;
    }

    public String getAuthor() {
        return author;
    }

    public List<String> getTags() {
        return tags;
    }
}
各例には、ループを使用した従来のソリューションと Java 8 の新機能を使用したソリューションが含まれます。最初の例では、コレクション内のタグ「Java」を持つ最初の記事を検索します。ループを使用した解決策を見てみましょう。
public Article getFirstJavaArticle() {

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            return article;
        }
    }
    return null;
}
次に、Stream API からの操作を使用して問題を解決しましょう。
public Optional<Article> getFirstJavaArticle() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .findFirst();
    }
かなりクールですね。まずこの操作を使用してfilter「Java」タグを持つすべての記事を検索し、次にfindFirst()を使用して最初の記事を取得します。ストリームは遅延しており、フィルターはストリームを返すため、このアプローチでは、最初の一致が見つかるまで要素のみが処理されます。ここで、最初の記事だけではなく、「Java」タグが付いたすべての記事を取得してみましょう。まずはループを使った解決策です。
public List<Article> getAllJavaArticles() {

    List<Article> result = new ArrayList<>();

    for (Article article : articles) {
        if (article.getTags().contains("Java")) {
            result.add(article);
        }
    }
    return result;
}
ストリーム操作を使用したソリューション。
public List<Article> getAllJavaArticles() {
    return articles.stream()
        .filter(article -> article.getTags().contains("Java"))
        .collect(Collectors.toList());
    }
collectこの例では、コレクションを宣言して一致するエントリを明示的に追加するのではなく、 操作を使用して結果のストリームを短縮しました。ここまでは順調ですね。Stream API を真に輝かせる例を見てみましょう。すべての記事を著者ごとにグループ化しましょう。いつものように、ループを使用して解決することから始めます。
public Map<String, List<Article>> groupByAuthor() {

    Map<String, List<Article>> result = new HashMap<>();

    for (Article article : articles) {
        if (result.containsKey(article.getAuthor())) {
            result.get(article.getAuthor()).add(article);
        } else {
            ArrayList<Article> articles = new ArrayList<>();
            articles.add(article);
            result.put(article.getAuthor(), articles);
        }
    }
    return result;
}
ストリーム操作を使用して、この問題に対する明確な解決策を見つけることはできるでしょうか?
public Map<String, List<Article>> groupByAuthor() {
    return articles.stream()
        .collect(Collectors.groupingBy(Article::getAuthor));
}
すばらしい!オペレーションgroupingByとメソッド参照を使用するとgetAuthor()、クリーンで読みやすいコードが得られます。次に、コレクションで使用されている残りのタグを見つけてみましょう。ループの例から始めましょう。
public Set<String> getDistinctTags() {

    Set<String> result = new HashSet<>();

    for (Article article : articles) {
        result.addAll(article.getTags());
    }
    return result;
}
さて、ストリーム操作を使用してこれを解決する方法を見てみましょう。
public Set<String> getDistinctTags() {
    return articles.stream()
        .flatMap(article -> article.getTags().stream())
        .collect(Collectors.toSet());
}
いいね!flatmapタグのリストを 1 つの結果ストリームに平坦化するのに役立ちます。その後、それを使用してcollect戻りセットを作成します。

無限の可能性

これらは、ループをより読みやすいコードに置き換える方法を示す 4 つの例です。この記事はほんの表面をなぞっただけなので、必ず Stream API を確認してください。Java の新しい関数型スタイルを習得することは、OOP 開発者にとって難しい課題ですが、それは歓迎されるべき課題です。さらに言えば、純粋な関数型プログラミング言語を学ぶべきだとも言えます。こうすることで、それが提供する機能とパワーを完全に理解できます。これは関数型プログラミングを別のレベルで理解するのに役立つと思います。したがって、関数型プログラミングと古き良き OOP を学び、両方を使用してさらに優れたコードを作成してください。2 つの記事の翻訳を自由に組み合わせたもの - Java 8 で関数型プログラミングを採用すべき理由Java 8 のループからの逸脱
コメント
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION