2014-10-27 36 views
7

से अगला आइटम प्राप्त करना मैं Stream बंद होने के बिना जावा 8 Stream से अगले आइटम को पुनर्प्राप्त करना और निकालना चाहता हूं।जावा 8 स्ट्रीम

Stream<Integer> integerStream = Stream.iterate(0, x -> new Integer(x + 1)); 
Integer zero = integerStream.getNext(); // 0 
Integer one = integerStream.getNext(); // 1 
... 

क्या यह संभव है?

+1

आप वास्तव में निकाले गए आइटम का उपयोग करने के लिए देख रहे हैं, या बस उन्हें त्यागें? उत्तरार्द्ध के लिए, '.skip (n)' ऐसा करने का तरीका है। –

उत्तर

1

Stuart's answer पर और एक Iterator-to-Stream conversion साथ आधार पर, मैं निम्नलिखित त्वरित और गंदा आवरण वर्ग के साथ आया था। यह परीक्षण नहीं किया गया है, और यह थ्रेड-सुरक्षित नहीं है, लेकिन यह मुझे वर्तमान में — को रखते हुए एकल आइटम को हटाने और उपयोग करने की आवश्यकता के साथ प्रदान करता है, यह स्ट्रीम "खुला" है।

PeelingStream<T> एक विधि T getNext() कि दूर someWrappedStream.iterator() के टर्मिनल धारा आपरेशन अर्थ विज्ञान ढाल प्रदान करता है:

public class PeelingStream<T> implements Stream<T> { 

    private Stream<T> wrapped; 

    public PeelingStream(Stream<T> toBeWrapped) { 
     this.wrapped = toBeWrapped; 
    } 

    public T getNext() { 
     Iterator<T> iterator = wrapped.iterator(); 
     T next = iterator.next(); 
     Iterable<T> remainingIterable =() -> iterator; 
     wrapped = StreamSupport.stream(remainingIterable.spliterator(), 
       false); 

     return next; 
    } 

    ///////////////////// from here, only plain delegate methods 

    public Iterator<T> iterator() { 
     return wrapped.iterator(); 
    } 

    public Spliterator<T> spliterator() { 
     return wrapped.spliterator(); 
    } 

    public boolean isParallel() { 
     return wrapped.isParallel(); 
    } 

    public Stream<T> sequential() { 
     return wrapped.sequential(); 
    } 

    public Stream<T> parallel() { 
     return wrapped.parallel(); 
    } 

    public Stream<T> unordered() { 
     return wrapped.unordered(); 
    } 

    public Stream<T> onClose(Runnable closeHandler) { 
     return wrapped.onClose(closeHandler); 

    } 

    public void close() { 
     wrapped.close(); 
    } 

    public Stream<T> filter(Predicate<? super T> predicate) { 
     return wrapped.filter(predicate); 
    } 

    public <R> Stream<R> map(Function<? super T, ? extends R> mapper) { 
     return wrapped.map(mapper); 
    } 

    public IntStream mapToInt(ToIntFunction<? super T> mapper) { 
     return wrapped.mapToInt(mapper); 
    } 

    public LongStream mapToLong(ToLongFunction<? super T> mapper) { 
     return wrapped.mapToLong(mapper); 
    } 

    public DoubleStream mapToDouble(ToDoubleFunction<? super T> mapper) { 
     return wrapped.mapToDouble(mapper); 
    } 

    public <R> Stream<R> flatMap(
      Function<? super T, ? extends Stream<? extends R>> mapper) { 
     return wrapped.flatMap(mapper); 
    } 

    public IntStream flatMapToInt(
      Function<? super T, ? extends IntStream> mapper) { 
     return wrapped.flatMapToInt(mapper); 
    } 

    public LongStream flatMapToLong(
      Function<? super T, ? extends LongStream> mapper) { 
     return wrapped.flatMapToLong(mapper); 
    } 

    public DoubleStream flatMapToDouble(
      Function<? super T, ? extends DoubleStream> mapper) { 
     return wrapped.flatMapToDouble(mapper); 
    } 

    public Stream<T> distinct() { 
     return wrapped.distinct(); 
    } 

    public Stream<T> sorted() { 
     return wrapped.sorted(); 
    } 

    public Stream<T> sorted(Comparator<? super T> comparator) { 
     return wrapped.sorted(comparator); 
    } 

    public Stream<T> peek(Consumer<? super T> action) { 
     return wrapped.peek(action); 
    } 

    public Stream<T> limit(long maxSize) { 
     return wrapped.limit(maxSize); 
    } 

    public Stream<T> skip(long n) { 
     return wrapped.skip(n); 
    } 

    public void forEach(Consumer<? super T> action) { 
     wrapped.forEach(action); 
    } 

    public void forEachOrdered(Consumer<? super T> action) { 
     wrapped.forEachOrdered(action); 
    } 

    public Object[] toArray() { 
     return wrapped.toArray(); 
    } 

    public <A> A[] toArray(IntFunction<A[]> generator) { 
     return wrapped.toArray(generator); 
    } 

    public T reduce(T identity, BinaryOperator<T> accumulator) { 
     return wrapped.reduce(identity, accumulator); 
    } 

    public Optional<T> reduce(BinaryOperator<T> accumulator) { 
     return wrapped.reduce(accumulator); 
    } 

    public <U> U reduce(U identity, 
      BiFunction<U, ? super T, U> accumulator, 
      BinaryOperator<U> combiner) { 
     return wrapped.reduce(identity, accumulator, combiner); 
    } 

    public <R> R collect(Supplier<R> supplier, 
      BiConsumer<R, ? super T> accumulator, BiConsumer<R, R> combiner) { 
     return wrapped.collect(supplier, accumulator, combiner); 
    } 

    public <R, A> R collect(Collector<? super T, A, R> collector) { 
     return wrapped.collect(collector); 
    } 

    public Optional<T> min(Comparator<? super T> comparator) { 
     return wrapped.min(comparator); 
    } 

    public Optional<T> max(Comparator<? super T> comparator) { 
     return wrapped.max(comparator); 
    } 

    public long count() { 
     return wrapped.count(); 
    } 

    public boolean anyMatch(Predicate<? super T> predicate) { 
     return wrapped.anyMatch(predicate); 
    } 

    public boolean allMatch(Predicate<? super T> predicate) { 
     return wrapped.allMatch(predicate); 
    } 

    public boolean noneMatch(Predicate<? super T> predicate) { 
     return wrapped.noneMatch(predicate); 
    } 

    public Optional<T> findFirst() { 
     return wrapped.findFirst(); 
    } 

    public Optional<T> findAny() { 
     return wrapped.findAny(); 
    } 

} 

एक छोटी सी परीक्षण:

@Test 
public void testPeelingOffItemsFromStream() { 

    Stream<Integer> infiniteStream = Stream.iterate(0, x -> x + 1); 

    PeelingStream<Integer> peelingInfiniteStream = new PeelingStream<>(infiniteStream); 

    Integer one = peelingInfiniteStream.getNext(); 
    assertThat(one, equalTo(0)); 

    Integer two = peelingInfiniteStream.getNext(); 
    assertThat(two, equalTo(1)); 

    Stream<Integer> limitedStream = peelingInfiniteStream.limit(3); // 2 3 4 
    int sumOf234 = limitedStream.mapToInt(x -> x.intValue()).sum(); 
    assertThat(sumOf234, equalTo(2 + 3 + 4)); 

} 
13

हां, ऐसा करने का एक तरीका है, लेकिन कुछ सीमाओं के साथ।

Stream<Integer> infiniteStream = Stream.iterate(0, x -> new Integer(x + 1)); 
Iterator<Integer> iter = infiniteStream.iterator(); 
Integer zero = iter.next(); 
Integer one = iter.next(); 

वैकल्पिक रूप से,

Stream<Integer> infiniteStream = Stream.iterate(0, x -> new Integer(x + 1)); 
Spliterator<Integer> spliterator = infiniteStream.spliterator(); 
spliterator.tryAdvance(i -> System.out.println(i)); // zero 
spliterator.tryAdvance(i -> System.out.println(i)); // one 

को देखते हुए एक Stream, यह इसे से एक Iterator या Spliterator प्राप्त करना संभव है, या क्या यह एक समानांतर धारा के प्रश्न के, आदि ये BaseStream इंटरफेस पर परिभाषित कर रहे हैं, Stream का एक सुपरइंटरफेस, जो उन्हें याद करने में थोड़ा आसान बनाता है।

इस मामले में हम जानते हैं धारा अनंत है, तो इटरेटर के hasNext() विधि कॉल करने या Spliterator के tryAdvance()

सीमा की वापसी मान की जाँच करने की कोई जरूरत नहीं है कि दोनों iterator() और spliterator() के तरीके Streamटर्मिनल ऑपरेशंस जिसका अर्थ है कि उन्हें कॉल करने के बाद, लौटा हुआ इटरेटर या स्प्लिटरेटर स्ट्रीम द्वारा प्रतिनिधित्व किए गए मानों तक विशेष पहुंच प्राप्त करता है। स्ट्रीम पर आगे के संचालन (जैसे कि filter या map और आगे) की अनुमति नहीं है और IllegalStateException से मुलाकात की जाएगी।

आप पहले दो तत्वों से दूर छील करने के लिए और फिर स्ट्रीम प्रसंस्करण को फिर से शुरू करना चाहता था, तो आप एक spliterator वापस एक धारा में तो जैसे बदल सकती है:

Stream<Integer> stream2 = StreamSupport.stream(spliterator, false); 

यह शायद कुछ बातों के लिए ठीक काम करेंगे, लेकिन मैं मुझे यकीन नहीं है कि मैं सामान्य रूप से इस तकनीक की सिफारिश करता हूं। मुझे लगता है कि यह कुछ अतिरिक्त वस्तुओं को जोड़ता है और इस प्रकार अगले तत्व के उत्पादन के रास्ते में अतिरिक्त विधि कॉल करता है।

संपादकीय टिप्पणियां (नहीं आपके प्रश्न से संबंधित):

  • new Integer(val) प्रयोग न करें। इसके बजाय Integer.valueOf(val) का उपयोग करें जो कि उपलब्ध होने पर बॉक्स किए गए पूर्णांक का पुन: उपयोग करेगा, जो आमतौर पर श्रेणी -128 से 127 के मानों के लिए सच है।
  • आप के बजाय IntStream का उपयोग कर सकते हैं जो पूरी तरह मुक्केबाजी ओवरहेड से बचाता है। इसमें स्ट्रीम ऑपरेशंस का पूर्ण पूरक नहीं है, लेकिन इसमें iterate() है जो एक ऐसा कार्य करता है जो आदिम int मानों पर संचालित होता है।
+3

या आप केवल 'x -> x + 1' का उपयोग कर सकते हैं जो छोटा है और' Integer.valueOf' का भी उपयोग करता है (अभी 8u25 और 'javap -c -p' के साथ सत्यापित)। –

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