यह जावा 9 समाधान सबसे अधिक संभावना कैसा दिखाई देगा की तरह है। flatMap
के माध्यम से मैचों की स्ट्रीम के साथ लाइनों की एक धारा का संयोजन करने से हम फ़ाइल के सभी मैचों को संसाधित कर सकते हैं। चूंकि आपका मूल कोड केवल एक पंक्ति के पहले मैच को संसाधित करता है, इसलिए मैंने एक ही व्यवहार प्राप्त करने के लिए प्रत्येक पंक्ति के मैचों में limit(1)
जोड़ा।
दुर्भाग्यवश, यह विशेषता जावा 8 में याद आ रही है, हालांकि, आगामी विज्ञप्ति में चुपके एक विचार हो रही मदद करता है की तरह एक अंतरिम समाधान लग सकता है कैसे:
Matcher m = Pattern.compile("name: '(.+)'").matcher("");
try(Stream<String> lines = Files.lines(ruleFile)) {
lines.flatMap(line -> m.reset(line).find()? Stream.of(m.toMatchResult()): null)
.forEach(mr -> System.out.println(mr.group(1)));
}
उप धारा निर्माण आसान बनाने के लिए, इस समाधान का इस्तेमाल करता है कि केवल पहला मैच इरादा है और पहले स्थान पर एकल तत्व स्ट्रीम बनाता है।
लेकिन ध्यान दें कि प्रश्न के पैटर्न 'name: '(.+)'
के साथ यह है कि क्या हम लालच से पिछले अनुवर्ती पंक्ति का '
अप करने के लिए सभी पात्रों से मेल खाएगी .+
के रूप में मैचों की संख्या को सीमित कोई फर्क नहीं पड़ता है, तो एक और मैच असंभव है। हालात अलग है जब name: '(.*?)'
साथ की तरह एक अनिच्छुक परिमाणक जो बल्कि पिछले एक से अगले'
अप करने के लिए खपत का उपयोग कर या, पिछले '
स्पष्ट रूप से छोड़ने के लिए मना name: '([^']*)'
साथ के रूप में कर रहे हैं।
उपयोग एक साझा Matcher
जो एकल पिरोया उपयोग के साथ अच्छी तरह से काम करता है (और यह कभी समानांतर प्रसंस्करण से लाभ होने की संभावना नहीं है) इसके बाद के संस्करण समाधान। लेकिन अगर आप धागा सुरक्षित पक्ष पर होना चाहता हूँ, आप केवल एक Pattern
का हिस्सा है और इसके बजाय m.reset(line)
बुलाने की एक Matcher
बना सकते हैं:
Pattern pattern = Pattern.compile("name: '(.*)'");
try(Stream<String> lines = Files.lines(ruleFile)) {
lines.flatMap(line -> pattern.matcher(line).results().limit(1))
.forEach(mr -> System.out.println(mr.group(1)));
}
resp। जावा 8
try(Stream<String> lines = Files.lines(ruleFile)) {
lines.flatMap(line -> {Matcher m=pattern.matcher(line);
return m.find()? Stream.of(m.toMatchResult()): null;})
.forEach(mr -> System.out.println(mr.group(1)));
}
जो स्थानीय चर के परिचय के कारण संक्षिप्त नहीं है।यह एक पूर्ववर्ती map
आपरेशन से बचा जा सकता है, लेकिन जब हम इस बिंदु पर के रूप में लंबे होते हैं, हम केवल प्रत्येक पंक्ति में एक भी मैच के लिए प्रमुख के रूप में, हम एक flatMap
तो जरूरत नहीं है:
try(Stream<String> lines = Files.lines(ruleFile)) {
lines.map(pattern::matcher).filter(Matcher::find)
.forEach(m -> System.out.println(m.group(1)));
}
प्रत्येक Matcher
के बाद से एक बार एक गैर-हस्तक्षेप करने के तरीके में, एक बार उपयोग किया जाता है, इसकी परिवर्तनीय प्रकृति यहां चोट नहीं पहुंची है और एक अपरिवर्तनीय MatchResult
में रूपांतरण अनावश्यक हो जाता है।
हालांकि, इन समाधान बार बार एक नया Matcher
वस्तु बनाने में, प्रत्येक पंक्ति में कई मैचों पर कार्रवाई करने के अगर वह कभी आवश्यक हो जाता है छोटा नहीं किया जा सकता ...
'मानचित्र (पी :: matcher)' पाइपलाइन चरण प्रत्येक पंक्ति के लिए एक नया 'Matcher' ऑब्जेक्ट बनाता है जो पढ़ने के लिए है। बहुत बड़ी फ़ाइलों के लिए, यह अक्षमता का स्रोत हो सकता है। इसके बजाए, एक पुन: प्रयोज्य 'Matcher' ऑब्जेक्ट बनाया जा सकता है, और' .map (matcher :: reset) 'का उपयोग लाइन से मैप करने के लिए किया जा सकता है, जिसे केवल पुन: प्रयोज्य 'matcher' में पढ़ा गया है, जैसा कि दिखाया गया है [https]//stackoverflow.com/a/47877960/3690024)। स्ट्रीम पाइपलाइनों में राज्यव्यापी वस्तुओं का पुन: उपयोग करने से सभी प्रकार के नियमों का उल्लंघन होता है, इसलिए यदि आप बड़ी फाइलें पढ़ रहे हैं, तो यह केवल इसकी सिफारिश करेगा, और यह एक बाधा बनने के लिए निर्धारित करें। – AJNeufeld