स्ट्रीम में जावा 8 फ़ॉरच लूप का उपयोग करके अगले आइटम पर जाएं


126

मुझे जावा 8 की धारा के साथ एक समस्या है जो लूप में अगले आइटम पर जाने की कोशिश कर रही है। मैं continue;केवल, जैसे कमांड सेट नहीं कर सकताreturn; काम करता है लेकिन आप इस मामले में लूप से बाहर निकल जाएंगे। मुझे लूप में अगले आइटम पर जाने की आवश्यकता है। मैं उसे कैसे कर सकता हूँ?

उदाहरण (काम नहीं):

try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
            filteredLines = lines.filter(...).foreach(line -> {
           ...
           if(...)
              continue; // this command doesn't working here
    });
}

उदाहरण (कार्य):

try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
    filteredLines = lines.filter(...).collect(Collectors.toList());
}

for(String filteredLine : filteredLines){
   ...
   if(...)
      continue; // it's working!
}

कृपया एक पूर्ण लेकिन न्यूनतम उदाहरण पोस्ट करें ताकि उत्तर देना आसान हो।
तुनकी

मुझे लूप में अगले आइटम पर जाने की आवश्यकता है।
विक्टर वी।

2
उनकी बात यह है कि आपके द्वारा दिखाए गए कोड के साथ, continueफिर भी किसी भी प्रकार के कार्यात्मक परिवर्तनों के बिना अगले आइटम पर नहीं चलेगा।
DoubleDouble

यदि लक्ष्य कॉल जारी रखने के बाद आने वाली लाइनों को निष्पादित करने से बचना है, और यह कि आप हमें नहीं दिखा रहे हैं, तो बस इन सभी लाइनों को एक elseब्लॉक में रखें। अगर इसके बाद कुछ नहीं है continue, तो अगर ब्लॉक और जारी रखें: वे बेकार हैं।
जेबी निज़ात

जवाबों:


278

का उपयोग करना return;ठीक काम करेगा। यह पूर्ण लूप को पूरा करने से नहीं रोकेगा। यह केवल forEachलूप के वर्तमान पुनरावृत्ति को निष्पादित करना बंद कर देगा ।

निम्नलिखित छोटे कार्यक्रम का प्रयास करें:

public static void main(String[] args) {
    ArrayList<String> stringList = new ArrayList<>();
    stringList.add("a");
    stringList.add("b");
    stringList.add("c");

    stringList.stream().forEach(str -> {
        if (str.equals("b")) return; // only skips this iteration.

        System.out.println(str);
    });
}

आउटपुट:

a
c

ध्यान दें कि कैसे पुनरावृत्ति के return;लिए निष्पादित किया जाता है b, लेकिन cनिम्नलिखित पुनरावृत्ति पर प्रिंट ठीक है।

यह काम क्यों करता है?

पहली बार में व्यवहार अनुचित लगने का कारण यह है क्योंकि हम returnपूरे विधि के निष्पादन में बाधा डालने वाले बयान के लिए उपयोग किए जाते हैं । इसलिए इस मामले में, हम उम्मीद करते हैं कि mainविधि का निष्पादन एक पूरे के रूप में किया जाएगा।

हालांकि, समझने की जरूरत है कि एक लंबोदर अभिव्यक्ति, जैसे:

str -> {
    if (str.equals("b")) return;

    System.out.println(str);
}

... वास्तव में इसकी अपनी अलग "विधि" के रूप में माना जाना चाहिए main, यह विधि से पूरी तरह से अलग है , इसके बावजूद यह आसानी से इसके भीतर स्थित है। तो वास्तव में, returnबयान केवल लंबोदर अभिव्यक्ति के निष्पादन को रोक देता है।

दूसरी बात जिसे समझने की आवश्यकता है, वह है:

stringList.stream().forEach()

... वास्तव में कवर के नीचे एक सामान्य लूप है जो हर पुनरावृत्ति के लिए लंबोदर अभिव्यक्ति को निष्पादित करता है।

इन 2 बिंदुओं को ध्यान में रखते हुए, उपरोक्त कोड को निम्नलिखित समकक्ष तरीके से (केवल शैक्षिक उद्देश्यों के लिए) फिर से लिखा जा सकता है:

public static void main(String[] args) {
    ArrayList<String> stringList = new ArrayList<>();
    stringList.add("a");
    stringList.add("b");
    stringList.add("c");

    for(String s : stringList) {
        lambdaExpressionEquivalent(s);
    }
}

private static void lambdaExpressionEquivalent(String str) {
    if (str.equals("b")) {
        return;
    }

    System.out.println(str);
}

इस "कम जादू" कोड के साथ, returnबयान का दायरा अधिक स्पष्ट हो जाता है।


3
मैंने पहले ही इस तरह की कोशिश की है और कुछ समय में यह काम नहीं करता है, मैंने इस चाल को फिर से दोहराया है और यह काम कर रहा है। धन्यवाद, यह मेरी मदद करता है। लगता है मैं सिर्फ overworked =)
विक्टर वी।

2
एक जादू की तरह काम करता है! क्या आप एक स्पष्टीकरण जोड़ सकते हैं कि यह काम क्यों करता है?
स्पार्कसाइडर

2
@ स्पाइडर: जोड़ा गया।
sstan

5

एक अन्य समाधान: अपने उल्टे स्थितियों के साथ एक फिल्टर के माध्यम से जाना: उदाहरण:

if(subscribtion.isOnce() && subscribtion.isCalled()){
                continue;
}

से बदला जा सकता है

.filter(s -> !(s.isOnce() && s.isCalled()))

सबसे सीधा दृष्टिकोण "वापसी" का उपयोग करते हुए प्रतीत होता है हालांकि।


2

आप जिस लैम्बडा से गुजर रहे हैं, forEach()उसका मूल्यांकन स्ट्रीम से प्राप्त प्रत्येक तत्व के लिए किया जाता है। लैंबडा के दायरे में से पुनरावृति स्वयं दिखाई नहीं देती है, इसलिए आप ऐसा नहीं कर सकते हैं continueजैसे कि forEach()सी प्रीप्रोसेसर मैक्रो थे। इसके बजाय, आप सशर्त रूप से इसमें दिए गए शेष कथनों को छोड़ सकते हैं।


0

आप ifजारी रखने के बजाय एक साधारण कथन का उपयोग कर सकते हैं । इसलिए जिस तरह से आपके पास अपना कोड है, आप कोशिश कर सकते हैं:

try(Stream<String> lines = Files.lines(path, StandardCharsets.ISO_8859_1)){
            filteredLines = lines.filter(...).foreach(line -> {
           ...
           if(!...) {
              // Code you want to run
           }
           // Once the code runs, it will continue anyway
    });
}

यदि कथन में विधेय आपके if(pred) continue;कथन में विधेय के विपरीत होगा , तो बस उपयोग करें !(तार्किक नहीं)।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.