मैं एक ऐसी धारा को लागू करने की कोशिश कर रहा हूं जो इसके कार्यान्वयन में स्वयं का एक और उदाहरण उपयोग करता है। धारा में कुछ निरंतर तत्व हैं (IntStream.concat के साथ), इसलिए यह तब तक काम करना चाहिए जब तक संगत धारा नॉन-निरंतर भाग को आलसी बनाता है। मुझे लगता है कि IntStream.concat ("creates a lazily concatenated stream") के साथ StreamSupport.intStream overload taking a Supplier का उपयोग करना चाहिए, जब तत्वों की मांग की जाती है तो केवल दूसरा स्प्लिटरेटर बनाने के लिए पर्याप्त आलसी होना चाहिए, लेकिन यहां तक कि स्ट्रीम (इसका मूल्यांकन नहीं) भी ढेर को बहती है। मैं आलसी धाराओं को कैसे जोड़ सकता हूं?मैं आलसी धाराओं को कैसे जोड़ूं?
मैं बंदरगाह के लिए प्रयास कर रहा हूँ जावा में this answer से स्ट्रीमिंग अभाज्य संख्या चलनी। यह चलनी पाइथन कोड में स्वयं का एक और उदाहरण (ps = postponed_sieve()
) का उपयोग करती है। अगर मैं अपने खुद के प्रवाह में प्रारंभिक चार लगातार तत्वों (yield 2; yield 3; yield 5; yield 7;
) को तोड़ने, यह एक spliterator के रूप में जनरेटर लागू करने के लिए आसान है:
/**
* based on https://stackoverflow.com/a/10733621/3614835
*/
static class PrimeSpliterator extends Spliterators.AbstractIntSpliterator {
private static final int CHARACTERISTICS = Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL | Spliterator.ORDERED | Spliterator.SORTED;
private final Map<Integer, Supplier<IntStream>> sieve = new HashMap<>();
private final PrimitiveIterator.OfInt postponedSieve = primes().iterator();
private int p, q, c = 9;
private Supplier<IntStream> s;
PrimeSpliterator() {
super(105097564 /* according to Wolfram Alpha */ - 4 /* in prefix */,
CHARACTERISTICS);
//p = next(ps) and next(ps) (that's Pythonic?)
postponedSieve.nextInt();
this.p = postponedSieve.nextInt();
this.q = p*p;
}
@Override
public boolean tryAdvance(IntConsumer action) {
for (; c > 0 /* overflow */; c += 2) {
Supplier<IntStream> maybeS = sieve.remove(c);
if (maybeS != null)
s = maybeS;
else if (c < q) {
action.accept(c);
return true; //continue
} else {
s =() -> IntStream.iterate(q+2*p, x -> x + 2*p);
p = postponedSieve.nextInt();
q = p*p;
}
int m = s.get().filter(x -> !sieve.containsKey(x)).findFirst().getAsInt();
sieve.put(m, s);
}
return false;
}
}
मेरे अभाज्य संख्या का पहला प्रयास() विधि एक IntStream साथ एक निरंतर प्रवाह श्रृंखलाबद्ध रिटर्न एक नया PrimeSpliterator:
public static IntStream primes() {
return IntStream.concat(IntStream.of(2, 3, 5, 7),
StreamSupport.intStream(new PrimeSpliterator()));
}
कॉलिंग अभाज्य संख्या() एक StackOverflowError में परिणाम क्योंकि अभाज्य संख्या() हमेशा एक PrimeSpliterator को दर्शाता है, लेकिन PrimeSpliterator के क्षेत्र प्रारंभकर्ता हमेशा अभाज्य संख्या कॉल()।
public static IntStream primes() {
return IntStream.concat(IntStream.of(2, 3, 5, 7),
StreamSupport.intStream(PrimeSpliterator::new, PrimeSpliterator.CHARACTERISTICS, false));
}
हालांकि, मैं बजाय (, छंटनी के रूप में यह दोहराता है) एक अलग पश्व-अनुरेखन के साथ एक StackOverflowError मिलती है: हालांकि, वहाँ है कि एक प्रदायक, जो lazily PrimeSpliterator बनाने की अनुमति चाहिए लेता StreamSupport.intStream की एक अधिभार है। ध्यान दें कि रिकर्स पूरी तरह से primes() पर कॉल में है - टर्मिनल ऑपरेशन इटरेटर() को लौटाई गई स्ट्रीम पर कभी भी नहीं बुलाया जाता है।
Exception in thread "main" java.lang.StackOverflowError
at java.util.stream.StreamSpliterators$DelegatingSpliterator$OfInt.<init>(StreamSpliterators.java:582)
at java.util.stream.IntPipeline.lazySpliterator(IntPipeline.java:155)
at java.util.stream.IntPipeline$Head.lazySpliterator(IntPipeline.java:514)
at java.util.stream.AbstractPipeline.spliterator(AbstractPipeline.java:352)
at java.util.stream.IntPipeline.spliterator(IntPipeline.java:181)
at java.util.stream.IntStream.concat(IntStream.java:851)
at com.jeffreybosboom.projecteuler.util.Primes.primes(Primes.java:22)
at com.jeffreybosboom.projecteuler.util.Primes$PrimeSpliterator.<init>(Primes.java:32)
at com.jeffreybosboom.projecteuler.util.Primes$$Lambda$1/834600351.get(Unknown Source)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.get(StreamSpliterators.java:513)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.estimateSize(StreamSpliterators.java:536)
at java.util.stream.Streams$ConcatSpliterator.<init>(Streams.java:713)
at java.util.stream.Streams$ConcatSpliterator$OfPrimitive.<init>(Streams.java:789)
at java.util.stream.Streams$ConcatSpliterator$OfPrimitive.<init>(Streams.java:785)
at java.util.stream.Streams$ConcatSpliterator$OfInt.<init>(Streams.java:819)
at java.util.stream.IntStream.concat(IntStream.java:851)
at com.jeffreybosboom.projecteuler.util.Primes.primes(Primes.java:22)
at com.jeffreybosboom.projecteuler.util.Primes$PrimeSpliterator.<init>(Primes.java:32)
at com.jeffreybosboom.projecteuler.util.Primes$$Lambda$1/834600351.get(Unknown Source)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.get(StreamSpliterators.java:513)
at java.util.stream.StreamSpliterators$DelegatingSpliterator.estimateSize(StreamSpliterators.java:536)
at java.util.stream.Streams$ConcatSpliterator.<init>(Streams.java:713)
at java.util.stream.Streams$ConcatSpliterator$OfPrimitive.<init>(Streams.java:789)
at java.util.stream.Streams$ConcatSpliterator$OfPrimitive.<init>(Streams.java:785)
at java.util.stream.Streams$ConcatSpliterator$OfInt.<init>(Streams.java:819)
at java.util.stream.IntStream.concat(IntStream.java:851)
at com.jeffreybosboom.projecteuler.util.Primes.primes(Primes.java:22)
मैं धाराओं lazily पर्याप्त एक धारा इसके कार्यान्वयन में खुद की एक प्रति का उपयोग करने की अनुमति कैसे जोड़ सकते हैं?
@8484 यह कन्स्ट्रक्टर में दो बार उन्नत है, इसलिए मुझे नहीं लगता कि यह आलसी-प्रारंभिक कैसे हो सकता है। (मुझे लगता है कि प्रश्न अभी भी मान्य है, यह देखते हुए कि IntStream.concat को आलसी होने के लिए कैसे दस्तावेज किया गया है।) –
यह आलसी धारा से संबंधित नहीं है, लेकिन 'x -> x + 2 * p' संभावित रूप से एक बग है क्योंकि 'p' एक सदस्य चर है जो लैम्ब्डा का मूल्यांकन करने से पहले बदल सकता है। – Misha