2015-09-11 5 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 ब्लॉक के बगल में एक चर के मान को सेट करना चाहता हूं, क्या यह काम कर सकता है?जावा 8 में, लैम्बडास फोरैच ब्लॉक में वैश्विक मूल्य कैसे सेट करें?

2. और क्यों?

3. और foreach iterator आदेश या विकार में है?

4. मुझे लगता है कि लैमडास फोरैच ब्लॉक इटेटरेटर के लिए अच्छा और सरल है, लेकिन यह वास्तव में जावा 7 या उससे पहले के काम के बजाए करना एक जटिल बात है।

+2

अपने पाश 'द्वारा अगर (list.stream() को फिल्टर (" डी ":: बराबर होती है (उदाहरण के लिए) बदला जा सकता है) .findAny () .isPresent()) x = "मान से मेल खाता है"; '। ज्यादातर स्थितियों में, बाहरी चरों को कुशलतापूर्वक इस्तेमाल किए बिना कोड लिखने का एक तरीका होगा। – assylias

+2

@assylias: 'if (list.stream()। AnyMatch (" d ":: बराबर)) ...' या 'if (list.contains (" d ")) ...' – Holger

+1

@ होल्गर अरघ - मैं हमेशा इसके बारे में भूल जाता हूं विधि (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. आप filter और map का उपयोग करके और अधिक संक्षेप में प्राप्त कर सकते हैं।

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

सामान्य lambdas में मित्र कार्यात्मक प्रोग्रामिंग के साथ आप शायद ही कभी परिवर्तनशील चर (हर चर केवल एक बार असाइन किया गया है) है, जहां कर रहे हैं। यदि आप लैम्ब्डा का उपयोग करते हैं, लेकिन अनिवार्य शैली में सोचते रहें तो आपको हमेशा ऐसी समस्याएं रहेंगी।

+3

एक साइड नोट के रूप में, आपका कोड वास्तव में ओपी के कोड से मेल खाता है कि '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 के लिए अनुशंसा नहीं करता। इसके विपरीत यदि समानांतर प्रवाह के लिए उपयोग किया जाता है तो यह दृष्टिकोण समझ में आता है। – dmachop

संबंधित मुद्दे