2017-06-02 15 views
1

ストリームを使用してリストの各要素の関数を呼び出すことが可能かどうかを知りたい場合は、の値に変更します。JAVAのリストの各要素で関数を実行する方法は?

のは、私は整数のリストを持っているとしましょう:List<Integer> list = Arrays.asList(1,2,3);

そして、もう一つですべての番号をインクリメントする方法:

public static Integer plusOne(Integer n){ 
    return n + 1; 
} 

これは私が各要素に対して関数を呼び出して変更するために使用するものです元のリスト:

for (int i = 0; i < list.size(); i++){ 
    list.set(i, plusOne(list.get(i))); 
} 

ただし、ストリームを使用してこれを書き込む方法があるかどうかを知りたかったですか?

私が使用してみました:

list.stream() 
    .forEach(e -> plusOne(e)); 

をしかし、それはストリームを使用して、元のリストを変更することは不可能だ場合、どのように私は、少なくとも取得することができます...元のリストを変更するように見える、また何も返しませんリストの新しい変更コピー?

出力は、リストで関数を呼び出した後の(2,3,4)のリストでなければなりません。

+1

あなたはストリームを反復しているコレクションを変異さ代わりにmap' ' – Li357

+1

を使用して開始するために非常に悪いアイデアのように思える:あなただけList.replaceAllを使用することができます。更新された値で新しい 'List'を生成する方がよいでしょう。 – Mena

+3

ストリームの多くの利点の1つは、データ構造を変更することをやめさせることです。 – slim

答えて

2

あなたは例えば、既存のリストを変更しないだけでstreamようcollectmapを使用する必要があります。

public static int plusOne(int i){ 
    return i + 1; 
} 

public static void main(String[] args) throws Exception{ 
    List<Integer> list = Arrays.asList(1,2,3); 
    List<Integer> updated = list.stream() 
      .map(i -> plusOne(i)) 
      .collect(Collectors.toList()); 
    System.out.println(updated); 
} 

あるいは、

List<Integer> updated = list.stream() 
      .map(i -> i + 1) 
      .collect(Collectors.toList()); 
    System.out.println(updated); 
+0

Darshan Mehtaありがとうございました! – Engineer

1

を通してそれをストリーミングしながら、あなたはあなたのListを変異させることができますイディオムに続いて。これは絶対に恐ろしいコードあり、かつ完全に恐ろしい練習を構成する

注意。

実験のためのみです。

List<Integer> list = Arrays.asList(1,2,3); 
// cannot have a re-assignable index here as it requires being effectively final 
int[] i = {0}; 
// iterating list 
list.forEach(
    // for each element... 
    (e) -> 
    // setting list at current index and incrementing index, with current value + 1 
    list.set(i[0]++, e + 1) 
); 
System.out.println(list); 

出力

[2, 3, 4] 

ノート

  • が流れのない並列処理がなく、インデクシングアレイコンテナが変異されているので、これは上記のイディオムで動作します予測可能に。
  • お勧めは、ストリーミング彼らの増加に値をマッピングし、Listとして収集することにより、新しいListを生成することである(些細な例えばDarshanの答えの第二部を参照)
+0

ありがとうございました。私は 'i [0] ++'の部分について質問したかったのですが、これまでにこのようなインデックスの使い方は見たことがありません。この方法についての情報がどこにあり、なぜ通常のintが機能しないのか知っていますか? – Engineer

+0

@エンジニア大歓迎です。配列ベースの索引付け(単純な 'int'とは対照的に)で起こっていることは、ラムダ内では、メソッドのローカルスコープの変数(他のものの中でも)を参照するのが効果的にfinalでなければならないということです。しかし、 'final int'を複数回明示的に割り当てることはできません。しかし、あなたは 'int []'を変更することができます。または 'AtomicInteger'です。 – Mena

+0

@Engineerは、私があなたに示した解決策のもう一つの赤い旗である、一般的な練習よりも "パーラートリック"に近いことを注記します。 – Mena

1

の方法がありますが、入力リストを変更する際に問題が発生するため、入力リストを変更することは避けてください。

あなたはかなり簡単に、新しいリストを(現在のスコープで)既存のリストを置き換えることができます。

list = list.stream().map(...).collect(Collectors.toList()); 

これはきれいです。あなたの古いリストはまだ存在します(ガベージコレクションの可能性があるまで)。それに対する他の言及は変化が見られません - それは健康です。これ以上参照がない場合は、ガベージコレクションされます。

+0

非常にスリムありがとう!だから、オリジナルのオブジェクトの値を変更する必要がないという目的のためにストリームが作成されたと言っていますか? – Engineer

+0

元のオブジェクトの値を変更することは決してありませんでした。しかし、ストリームはあなたがしないコードを推奨します。 – slim

2

ストリームが不要です。

list.replaceAll(MyApplication::plusOne); 
関連する問題