2015-07-21 10 views
6

Penso di aver riscontrato un problema con un'ipotesi che ho fatto: se un elemento dello spliterator non viene consumato da un flusso, lo spliterator sarà ancora in grado di avanzare verso di esso. Sembra che questo non sia il caso.Stato splitterator dopo "consumato" in Stream

Ecco po 'di codice per dimostrare:

import java.util.Spliterator; 
import java.util.function.Function; 
import java.util.stream.Collectors; 
import java.util.stream.Stream; 
import java.util.stream.StreamSupport; 

/** 
* Created by dsmith on 7/21/15. 
*/ 
public class SpliteratorTest { 
    public static void main(String[] args) { 
     System.out.println("Test 1"); 
     test1(); 

     System.out.println("Test 2"); 
     test2(); 
    } 

    public static void test1() { 
     final Spliterator<String> spliterator1 = Stream.of("a", "b", "c", "d", "e", "f").spliterator(); 

     StreamSupport.stream(spliterator1, false). 
       limit(3). 
       collect(Collectors.toList()); 

     System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize()); 
    } 

    public static void test2() { 
     final Spliterator<String> spliterator1 = Stream.of("a", "b", "c", "d", "e", "f").spliterator(); 
     final Spliterator<String> spliterator2 = Stream.of("1", "2", "3", "4", "5", "6").spliterator(); 

     Stream.of(StreamSupport.stream(spliterator1, false), StreamSupport.stream(spliterator2, false)). 
       flatMap(Function.identity()). 
       limit(3). 
       collect(Collectors.toList()); 

     System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize()); 
     System.out.println("spliterator2.estimateSize() = " + spliterator2.estimateSize()); 
    } 
} 

Questo uscite:

Test 1 
spliterator1.estimateSize() = 3 
Test 2 
spliterator1.estimateSize() = 0 
spliterator2.estimateSize() = 6 

Capisco che spliterators possono essere divisi ... ma sembra che non diviso, accesso sequenziale sarebbe intuitivamente preservare articoli non consumati.

Nel test2, sembra che lo spliterator1 sia completamente consumato dopo il flusso. Ma in test1, non è completamente consumato.

C'è qualcosa che posso fare per ottenere il comportamento desiderato o sto facendo qualcosa che non dovrei fare?

+1

La messaggistica con lo stato dello splitterator dopo che sono stati utilizzati in un flusso sarà sicuramente un comportamento indefinito che non si suppone stia facendo. –

+1

Vedere http://stackoverflow.com/q/29229373/2711488 – Holger

risposta

5

Questo è un dettaglio di implementazione, ma il modo in cui funziona flatMap attualmente è che non viene diviso nel suo contenuto o iterato su di esso un elemento alla volta. Si divora tutto in una volta. Se lo fai, invece di Stream.concat(...)flatMap, si dovrebbe vedere la differenza:

Stream.concat(StreamSupport.stream(spliterator1, false), StreamSupport.stream(spliterator2, false)). 
     limit(3). 
     collect(Collectors.toList()); 

System.out.println("spliterator1.estimateSize() = " + spliterator1.estimateSize()); 
System.out.println("spliterator2.estimateSize() = " + spliterator2.estimateSize()); 

uscita:

spliterator1.estimateSize() = 3 
spliterator2.estimateSize() = 6 

sto solo facendo una cosa che non dovrei fare?

In breve, sì. La libreria Streams non promette in quale stato lascerà uno splitterator dopo un attraversamento parziale.