In java8, how to set the global value in the lambdas foreach block?

前端 未结 4 1490
予麋鹿
予麋鹿 2020-12-01 10:49
    public void test(){
       String x;
       List list=Arrays.asList(\"a\",\"b\",\"c\",\"d\");

       list.forEach(n->{
          if(n.equals(\"         


        
相关标签:
4条回答
  • 2020-12-01 10:56

    As it's already explained, you cannot modify the local variable of the outer method from the lambda body (as well as from the anonymous class body). My advice is don't try to use lambdas when they are completely unnecessary. Your problem can be solved like this:

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

    In general lambdas are friends with functional programming where you rarely have mutable variables (every variable is assigned only once). If you use lambdas, but continue thinking in imperative style you will always have such problems.

    0 讨论(0)
  • 2020-12-01 10:59

    You could, of course, "make the outer value mutable" via a trick:

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

    Get ready for a beating by the functional purist on the team, though. Much nicer, however, is to use a more functional approach (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);
    }
    
    0 讨论(0)
  • 2020-12-01 11:08
    1. No you can't do it. (Although you should have tried it yourself)
    2. Because variables used within anonymous inner classes and lambda expression have to be effectively final.
    3. you can achieve the same more concisely using filter and map.

      Optional<String> d = list.stream()
                               .filter(c -> c.equals("d"))
                               .findFirst()
                               .map(c -> "match the value");
      
    0 讨论(0)
  • 2020-12-01 11:15

    In addition to already provided idiomatic examples, another hack would be to use AtomicReference, but I would only recommend it if you do need 'forEach' and prefer something more readable than true-functional variant:

    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");
        });
    }
    
    0 讨论(0)
提交回复
热议问题