मुझे पता है कि जावा में कोई सीधा बराबर नहीं है, लेकिन शायद एक तीसरी पार्टी है?
यह वास्तव में सुविधाजनक है। वर्तमान में मैं एक ट्रीटर को लागू करना चाहता हूं जो एक पेड़ में सभी नोड्स पैदा करता है, जो उपज के साथ कोड की पांच पंक्तियों के बारे में है।
मुझे पता है कि जावा में कोई सीधा बराबर नहीं है, लेकिन शायद एक तीसरी पार्टी है?
यह वास्तव में सुविधाजनक है। वर्तमान में मैं एक ट्रीटर को लागू करना चाहता हूं जो एक पेड़ में सभी नोड्स पैदा करता है, जो उपज के साथ कोड की पांच पंक्तियों के बारे में है।
जवाबों:
दो विकल्प मुझे पता है कि 2007 से एवाड बेन डोव के इन्फोमेंसर-संग्रह पुस्तकालय और 2008 से जिम ब्लैकलर की यील्डएडैप्टर लाइब्रेरी है (जो अन्य उत्तर में भी वर्णित है)।
दोनों आपको yield return
जावा में समान निर्माण के साथ कोड लिखने की अनुमति देंगे , इसलिए दोनों आपके अनुरोध को पूरा करेंगे। दोनों के बीच उल्लेखनीय अंतर हैं:
जिम की मल्टीथ्रेडिंग का उपयोग करते हुए एवाड की लाइब्रेरी बायटेकोड हेरफेर का उपयोग कर रही है। आपकी आवश्यकताओं के आधार पर, प्रत्येक के अपने फायदे और नुकसान हो सकते हैं। यह संभावना है कि एवाड का समाधान तेज है, जबकि जिम अधिक पोर्टेबल है (उदाहरण के लिए, मुझे नहीं लगता कि एवाड की लाइब्रेरी एंड्रॉइड पर काम करेगी)।
अविद की लाइब्रेरी में एक क्लीनर इंटरफ़ेस है - यहाँ एक उदाहरण है:
Iterable<Integer> it = new Yielder<Integer>() {
@Override protected void yieldNextCore() {
for (int i = 0; i < 10; i++) {
yieldReturn(i);
if (i == 5) yieldBreak();
}
}
};
जबकि जिम अधिक जटिल है, आपको adept
एक जेनेरिक की आवश्यकता है Collector
जो एक collect(ResultHandler)
विधि है ... उह। हालाँकि, आप ज़ूम इनफॉर्मेशन द्वारा जिम के कोड के आसपास इस रैपर जैसे कुछ का उपयोग कर सकते हैं जो कि बहुत सरल करता है:
Iterable<Integer> it = new Generator<Integer>() {
@Override protected void run() {
for (int i = 0; i < 10; i++) {
yield(i);
if (i == 5) return;
}
}
};
एविएड का समाधान बीएसडी है।
जिम का समाधान सार्वजनिक डोमेन है, और इसलिए इसका आवरण ऊपर वर्णित है।
AbstractIterator
।
yield(i)
JDK 13 के रूप में टूट जाएगा, क्योंकि yield
एक नया जावा स्टेटमेंट / आरक्षित कीवर्ड के रूप में जोड़ा जा रहा है।
इन दोनों दृष्टिकोणों को थोड़ा साफ किया जा सकता है अब जावा में लैम्ब्डा है। आप कुछ ऐसा कर सकते हैं
public Yielderable<Integer> oneToFive() {
return yield -> {
for (int i = 1; i < 10; i++) {
if (i == 6) yield.breaking();
yield.returning(i);
}
};
}
Yielderable
? यह सिर्फ नहीं होना चाहिए Yieldable
? (क्रिया सिर्फ 'उपज' किया जा रहा है, नहीं 'yielder' या 'yielderate' या जो कुछ भी)
yield -> { ... }
JDK 13 के रूप में टूट जाएगा, क्योंकि yield
एक नया जावा स्टेटमेंट / आरक्षित कीवर्ड के रूप में जोड़ा जा रहा है।
मुझे पता है कि यह एक बहुत पुराना सवाल है, और ऊपर वर्णित दो तरीके हैं:
yield
जो स्पष्ट रूप से संसाधन लागत है।हालांकि, yield
जावा में जनरेटर को लागू करने का एक और, तीसरा और शायद सबसे प्राकृतिक तरीका है, जो कि सी # 2.0+ कंपाइलरों को yield return/break
पीढ़ी के लिए क्या करता है के लिए निकटतम कार्यान्वयन है : लोमबोक-पीजी । यह पूरी तरह से एक राज्य मशीन पर आधारित है, और javac
स्रोत कोड एएसटी में हेरफेर करने के लिए तंग सहयोग की आवश्यकता है । दुर्भाग्य से, लुम्बोक-पीजी समर्थन को बंद किया जा रहा है (एक या दो साल से अधिक के लिए कोई रिपॉजिटरी गतिविधि नहीं है), और मूल प्रोजेक्ट लोम्बोक में दुर्भाग्य से इस yield
सुविधा का अभाव है (इसमें ग्रहण, इंटेलीजेंट आईडीईए समर्थन की तरह बेहतर आईडीई है, हालांकि)।
Stream.iterate (बीज, seedOperator) .limit (एन) .foreach (कार्रवाई) उपज ऑपरेटर के रूप में ही नहीं है, लेकिन यह अपने स्वयं के जनरेटर इस तरह से लिखने के लिए उपयोगी हो सकता है:
import java.util.stream.Stream;
public class Test01 {
private static void myFoo(int someVar){
//do some work
System.out.println(someVar);
}
private static void myFoo2(){
//do some work
System.out.println("some work");
}
public static void main(String[] args) {
Stream.iterate(1, x -> x + 1).limit(15).forEach(Test01::myFoo); //var1
Stream.iterate(1, x -> x + 1).limit(10).forEach(item -> myFoo2()); //var2
}
}
मैं यह भी सुझाव देता हूं कि यदि आप पहले से ही " येल्डर " के रूप में एक ऑब्जर्वेबल का उपयोग करने के लिए आरएक्सजाव का उपयोग कर रहे हैं । यदि आप अपने खुद के ऑब्जर्वेबल बनाते हैं तो इसका उपयोग इसी तरह से किया जा सकता है।
public class Example extends Observable<String> {
public static void main(String[] args) {
new Example().blockingSubscribe(System.out::println); // "a", "b", "c", "d"
}
@Override
protected void subscribeActual(Observer<? super String> observer) {
observer.onNext("a"); // yield
observer.onNext("b"); // yield
observer.onNext("c"); // yield
observer.onNext("d"); // yield
observer.onComplete(); // finish
}
}
वेधशालाओं को पुनरावृत्तियों में बदला जा सकता है, ताकि आप उन्हें लूप के लिए अधिक पारंपरिक रूप में भी उपयोग कर सकें। इसके अलावा RXJava आपको वास्तव में शक्तिशाली उपकरण देता है, लेकिन अगर आपको केवल कुछ सरल की आवश्यकता है, तो शायद यह एक ओवरकिल होगा।
मैंने अभी एक और (MIT- लाइसेंस प्राप्त) समाधान प्रकाशित किया है , जो निर्माता को एक अलग थ्रेड में लॉन्च करता है, और निर्माता और उपभोक्ता के बीच एक बंधी हुई कतार को स्थापित करता है, जिससे निर्माता और उपभोक्ता के बीच बफरिंग, फ्लो कंट्रोल और समानांतर पाइपलाइनिंग की अनुमति मिलती है (इसलिए उपभोक्ता पिछली वस्तु का उपभोग करने पर काम कर सकता है जबकि निर्माता अगले वस्तु के उत्पादन पर काम कर रहा है)।
आप इस अनाम आंतरिक वर्ग फॉर्म का उपयोग कर सकते हैं:
Iterable<T> iterable = new Producer<T>(queueSize) {
@Override
public void producer() {
produce(someT);
}
};
उदाहरण के लिए:
for (Integer item : new Producer<Integer>(/* queueSize = */ 5) {
@Override
public void producer() {
for (int i = 0; i < 20; i++) {
System.out.println("Producing " + i);
produce(i);
}
System.out.println("Producer exiting");
}
}) {
System.out.println(" Consuming " + item);
Thread.sleep(200);
}
या आप बॉयलरप्लेट में कटौती करने के लिए लैम्बडा नोटेशन का उपयोग कर सकते हैं:
for (Integer item : new Producer<Integer>(/* queueSize = */ 5, producer -> {
for (int i = 0; i < 20; i++) {
System.out.println("Producing " + i);
producer.produce(i);
}
System.out.println("Producer exiting");
})) {
System.out.println(" Consuming " + item);
Thread.sleep(200);
}