2015-06-11 10 views
18

Desidero raddoppiare uno Stream (no DoubleStream). Significa che inizio con un flusso e voglio ottenere un nuovo flusso in cui ogni elemento del vecchio stream viene trasmesso in streaming due volte. Quindi 1,2,3,4,4,5 ci dà 1,1,2,2,3,3,4,4,4,4,5,5. Esiste una tale operazione di streaming?Doppio stream

+5

Solo una nota: un altro approccio consiste semplicemente nel creare una vista della raccolta originale (o altra sorgente dello stream) che restituisce ogni elemento due volte. Non sto dicendo che è quello che dovresti fare, solo che è un'opzione e in certi casi l'approccio alla vista funziona meglio. – biziclop

+0

@biziclop: in realtà potrebbe essere più performante della soluzione 'flatMap' in quanto lo stream da tale vista sarà in grado di riportarne la dimensione esatta. –

+1

@TagirValeev E non richiede la creazione di 'n' flussi intermedi. – biziclop

risposta

28

Creare un flusso interno che conterrà l'elemento corrente due volte e flatMap questo flusso.

stream.flatMap(e -> Stream.of(e,e)) 

Se si vuole moltiplicare il numero di elementi da n è possibile creare un metodo di utilità come questo:

public static <T> Stream<T> multiplyElements(Stream<T> in, int n) { 
    return in.flatMap(e -> IntStream.range(0, n).mapToObj(i -> e)); 
    // we can also use IntStream.rangeClosed(1, n) 
    // but I am used to iterating from 0 to n (excluding n) 
} 

(ma tenta di utilizzare un nome migliore per questo metodo, in quanto la corrente uno può essere ambiguo) esempio

utilizzati:

multiplyElements(Stream.of(1,2), 3).forEach(System.out::println); 

Uscita:

1 
1 
1 
2 
2 
2 
+2

'repeatEach()' sarebbe probabilmente un buon nome :) –

+1

Da un punto di vista matematico un buon nome sarebbe 'diagonalize (Stream stream, int length)' perché la mappa A-> A^n invia x a (x, ..., x) si chiama embedding diagonale. –

6

È possibile creare un flusso di 2 elementi per ogni elemento originale e flatMap esso:

List<Integer> list = Arrays.asList(1, 2, 3, 4, 4, 5); 
List<Integer> doubled = list.stream().flatMap(i -> Stream.of(i, i)).collect(toList()); 
+4

IMHO dovresti menzionare le importazioni statiche, come 'Collectors.toList' – fabian

3

Ecco un semplice esempio di ciò che biziclop ha descritto nei commenti.

static <E> Collection<E> multiply(Collection<E> source, int count) { 
    return new AbstractCollection<E>() { 
     @Override 
     public int size() { 
      return count * source.size(); 
     } 
     @Override 
     public Iterator<E> iterator() { 
      return new Iterator<E>() { 
       final Iterator<E> it = source.iterator(); 

       E next; 
       int i = 0; 

       @Override 
       public boolean hasNext() { 
        return i < size(); 
       } 
       @Override 
       public E next() { 
        if (hasNext()) { 
         if ((i % count) == 0) { 
          next = it.next(); 
         } 
         ++i; 
         return next; 
        } else { 
         throw new NoSuchElementException(); 
        } 
       } 
      }; 
     } 
    }; 
} 

(esempio Lavorando su Ideone.)

CW'd dato che non era la mia idea e le flatMap suggerimenti rispondere più direttamente la domanda.