web-dev-qa-db-ja.com

javaのラムダforEach()から戻る

いくつかのfor-eachループをlambda forEach()- methodsに変更して、ラムダ式の可能性を発見しようとしています。フォローは可能だと思われます:

ArrayList<Player> playersOfTeam = new ArrayList<Player>();      
for (Player player : players) {
    if (player.getTeam().equals(teamName)) {
        playersOfTeam.add(player);
    }
}

ラムダforEach()を使用

players.forEach(player->{if (player.getTeam().equals(teamName)) {playersOfTeam.add(player);}});

しかし、次のものは機能しません:

for (Player player : players) {
    if (player.getName().contains(name)) {
        return player;
    }
}

ラムダ付き

players.forEach(player->{if (player.getName().contains(name)) {return player;}});

最後の行の構文に何か問題がありますか、forEach()メソッドから戻ることは不可能ですか?

72
samutamm

returnは、包含メソッドからではなく、ラムダ式から返されます。 forEachの代わりに、ストリームをfilterする必要があります。

players.stream().filter(player -> player.getName().contains(name))
       .findFirst().orElse(null);

ここで、filterは述語に一致する項目にストリームを制限し、findFirstは最初に一致するエントリでOptionalを返します。

これはforループアプローチよりも効率が悪いように見えますが、実際にはfindFirst()は短絡する可能性があります-フィルター処理されたストリーム全体を生成してから1つの要素を抽出するのではなく、できるだけ多くの要素のみをフィルター処理します最初に一致するものを見つけるために必要です。 first一致するプレーヤーを(順序付けされた)ストリームから取得するだけでなく、単に一致するアイテムを取得する必要がない場合は、findAny()の代わりにfindFirst()を使用することもできます。これにより、並列処理が含まれる場合の効率が向上します。

97
Ian Roberts

最初に全体像でJava 8を理解することをお勧めします。最も重要なのは、ストリーム、ラムダ、メソッド参照です。

既存のコードを行ごとにJava 8コードに変換し、neverする必要があります。機能を抽出し、それらを変換する必要があります。

最初のケースで特定したのは次のとおりです。

  • 何らかの述語と一致する場合、入力構造の要素を出力リストに追加します。

それをどのように行うかを見てみましょう。次のようにできます:

List<Player> playersOfTeam = players.stream()
    .filter(player -> player.getTeam().equals(teamName))
    .collect(Collectors.toList());

ここで行うことは:

  1. 入力構造をストリームに変換します(ここではCollection<Player>型であると仮定していますが、現在はStream<Player>があります。
  2. Predicate<Player>を使用してすべての不要な要素を除外し、すべてのプレーヤーを保持する場合はブール値trueにマッピングします。
  3. Collectorを使用して、結果の要素をリストに収集します。ここでは、標準ライブラリコレクターの1つであるCollectors.toList()を使用できます。

これには、他の2つのポイントも組み込まれています。

  1. インターフェイスに対するコード。したがって、List<E> over ArrayList<E>に対するコード。
  2. new ArrayList<>()のtypeパラメーターにひし形の推論を使用します。結局、Java 8を使用しています。

次に、2番目のポイントに進みます。

大きな画像を見ずに、従来のJavaをJava 8に変換したい場合があります。この部分はすでに @ IanRoberts によって回答されていますが、彼が提案したことに対してplayers.stream().filter(...)...を行う必要があると思います。

11
skiwi

ブール値を返したい場合は、次のようなものを使用できます(フィルターよりもはるかに高速です):

players.stream().anyMatch(player -> player.getName().contains(name));
4
Sriram

これが私を助けたもの:

List<RepositoryFile> fileList = response.getRepositoryFileList();
RepositoryFile file1 = fileList.stream().filter(f -> f.getName().contains("my-file.txt")).findFirst().orElse(null);

Lambdaでリスト内の特定の要素を見つけるJava 8 から取得

4
user5495300