web-dev-qa-db-ja.com

Java8では、ラムダforeachブロックにグローバル値を設定する方法は?

    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ブロックの横に変数の値を設定したいのですが、動作しますか?

2.そしてなぜ?

3.そして、foreachイテレータは正常に機能していますか?

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

27
MarsYoung

もちろん、トリックを介して「外部値を可変にする」こともできます。

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";
    });
}

ただし、チームの機能的純粋主義者による暴行の準備をしてください。ただし、より機能的なアプローチを使用する方がはるかに優れています( Sleimanのアプローチと同様 ):

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);
}
23
Lukas Eder

すでに提供されている慣用的な例に加えて、別のハックは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");
    });
}
9
Andrii Rubtsov
  1. いいえ、できません。 (自分で試してみるべきでしたが)
  2. 匿名の内部クラスおよびラムダ式内で使用される変数はeffectively finalである必要があるためです。
  3. filtermapを使用して、同じことをより簡潔に実現できます。

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

既に説明したように、ラムダ本体(および匿名クラス本体)から外部メソッドのローカル変数を変更することはできません。私のアドバイスは、ラムダが完全に不要な場合にラムダを使用しようとしないことです。問題は次のように解決できます。

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

一般に、ラムダは関数型プログラミングのフレンドであり、変更可能な変数はめったにありません(すべての変数は一度しか割り当てられません)。ラムダを使用するが、命令型のスタイルで考え続けると、常にこのような問題が発生します。

6
Tagir Valeev