質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.49%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

2回答

1417閲覧

Java8ラムダ式について

gmkzmrn

総合スコア13

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

1グッド

1クリップ

投稿2017/06/12 11:19

Java8で実装されたラムダ式を勉強しておりますが
どうもうまくいきません。

どこがわるいのでしょう
ソースはリストに対してそれぞれ2倍したい、という内容です。

Java

1 2package lamda; 3 4import java.util.ArrayList; 5import java.util.List; 6public class Lamda_test { 7 public static void main(String[] args){ 8 List<Integer> list = new ArrayList<Integer>(); 9 list.add(1); 10 list.add(2); 11 list.add(3); 12 list.stream().forEach(i -> i*2); 13 } 14} 15
DrqYuto👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

うまくいかない原因はlambda式の使い方ではなくてStream APIについての勘違いのようです。

Stream APIではパイプラインの各段は前のパイプラインから受け取った値を計算して次のパイプラインへ渡す(複数のパイプラインの間で流れ作業のように要素を加工していく)のが基本です。パイプラインの最終段は終端操作と呼ばれ、以下のいずれかを行います。

(A) 前段までのパイプラインで計算された結果を最終的な値へ変換(蓄積, 簡約, etc.)
(B) 前段までのパイプラインで計算された各要素の値を使って副作用を起こす

ご質問のコードにあるforEachは(B)のためのメソッドですが、各要素を2倍してはいるものの、それを元のリストへ書き戻すことができていません。

各要素を2倍したリストを作るのは(A),(B)いずれの考え方でもできます。

(A)の考え方

java

1list = list.stream() // (1) 2 .map(i -> i * 2) // (2) 3 .collect(Collectors.toList()); // (3)

(1) のリストの各要素をパイプラインへ渡す
(2) (1)から受け取った各要素を2倍して次のパイプラインへ渡す
(3) (2)から受け取った各要素をListへ蓄積(Collect)し、全要素を集め終わったら結果を返す

(B)の考え方

java

1IntStream.range(0, list.size()).forEach(i -> 2 list.set(i, list.get(i) * 2) // 要素を取り出し2倍し元の値を書き換える(副作用) 3);

forEachの方は副作用(元のリストへ計算結果を書き戻す)ためにインデックスが必要なため、パイプライン上へ要素の値ではなくインデックスを流しています。(個人的には)for文を使うのと大差ないように思えます。


追記:swordoneさんコメントのように、Stream APIに副作用を用いると注意が必要です。一般には(A)を使い、パイプラインの各段には「副作用がない関数操作のみに限定する」のがお勧めと思います。

投稿2017/06/12 12:18

編集2017/06/12 12:37
KSwordOfHaste

総合スコア18394

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

swordone

2017/06/12 12:27 編集

この(B)の方法は外部変数に干渉してしまうためステートレスになりません。
KSwordOfHaste

2017/06/12 12:28 編集

インデックスのストリームなのですが干渉しますか? --- あ・・・一般のストリームとしてはよくないということでしょうかね。そういう意味ならおっしゃるとおりと思います。
swordone

2017/06/12 12:27

勘違いしました。コメント編集しました。
KSwordOfHaste

2017/06/12 12:31

副作用前提なので制約をよく把握せずに使うとイケナイことがおきそうです。 例えば隣同士の要素に依存した簡約操作&並列動作させるとアウトですね。
gmkzmrn

2017/06/12 20:23

とても勉強になりました。 ありがとうございます
guest

0

map使いましょう。

投稿2017/06/12 12:16

ozwk

総合スコア13521

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.49%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問