2015-09-11 20 views
16
public void test(){ 
     String x; 
     List<String> list=Arrays.asList("a","b","c","d"); 

     list.forEach(n->{ 
      if(n.equals("d")) 
      x="match the value"; 
     }); 
    } 

1.上記のコードのように、foreachブロックの横にある変数の値を設定したいのですが、それは動作しますか?java8では、lambdas foreachブロックのグローバル値を設定する方法は?

2.なぜですか?

3. foreachイテレータは順不同ですか?

4.私はlamdas foreachブロックがイテレーターにとってクールでシンプルだと思いますが、これはJava 7以前と同じ作業ではなく、実際には複雑なことです。

+2

あなたのループは '場合(list.stream()によって(例えば)に交換することができ、 "D"(フィルタリング::等しい).findAny(。 ).isPresent())x = "値に一致する";ほとんどの場合、外部変数を操作することなくコードを書く方法があります。 – assylias

+2

@assylias: '(list.stream()。anyMatch(" d ":: equals))...またはif(list.contains(" d "))... ' – Holger

+1

@Holger Argh - 私はいつもそれを忘れていますメソッド(anyMatch)とはい、確かに、より良い含まれています。ありがとう! – assylias

答えて

20

public void test() { 
    String[] x = new String[1]; 
    List<String> list = Arrays.asList("a", "b", "c", "d"); 

    list.forEach(n -> { 
     if (n.equals("d")) 
      x[0] = "match the value"; 
    }); 
} 

はいえ、チームの機能純粋主義者による暴行のための準備をしなさい。非常に良く、しかし、より機能的アプローチ(similar to Sleiman's approach)を使用することです: 'は既に慣用的な例を提供するほか

public void test() { 
    List<String> list = Arrays.asList("a", "b", "c", "d"); 
    String x = list.stream() 
        .filter("d"::equals) 
        .findAny() 
        .map(v -> "match the value") 
        .orElse(null); 
} 
7
  1. いいえ、できません。
  2. 匿名の内部クラスとラムダ式で使用される変数はeffectively finalである必要があるため、自分で試してみてください。
  3. filtermapを使用すると、より簡潔に同じことを達成できます。

    Optional<String> d = list.stream() 
             .filter(c -> c.equals("d")) 
             .findFirst() 
             .map(c -> "match the value"); 
    
5

それは既に説明しています、あなたは、ラムダ本体から(だけでなく、匿名クラスのボディから)外側のメソッドのローカル変数を変更することはできません。私のアドバイスは、ラムダが完全に不要なときにラムダを使用しようとしないことです。あなたの問題は次のように解決することができます:一般ラムダに

public void test(){ 
    String x; 
    List<String> list = Arrays.asList("a","b","c","d"); 
    if(list.contains("d")) 
     x = "match the value"; 
} 

あなたはめったに変更可能な変数を(すべての変数は一度だけ割り当てられている)持っていない関数型プログラミングと友達です。あなたがラムダを使用しても、命令的なスタイルで考え続けるなら、あなたはいつもそうした問題を抱えています。あなたは、もちろん、トリックを経由して「外側の値は可変にする」ことができ

+3

補足として、あなたのコードは実際にOPのコードにマッチします。というのも、 'x'は割り当てられないかもしれないので、その後はまったく役に立たないということです。 – Holger

7

を、別のハックはAtomicReferenceを使用することですが、あなたが必要とするならば、私はそれをお勧めしますforEachの」と真の機能的変異体よりも読みやすいものを好む:

public void test(){ 
    AtomicReference<String> x = new AtomicReference<>(); 
    List<String> list= Arrays.asList("a", "b", "c", "d"); 

    list.forEach(n->{ 
     if(n.equals("d")) 
      x.set("match the value"); 
    }); 
} 
+1

foreachのために推奨しないけれども、 'AtomicReference'のためにUpvoted。その代わりに、このアプローチは、並列ストリームに使用すると意味があります。 – dmachop

関連する問題