雙流

2015-06-11 33 views
18

我想加倍Stream(沒有DoubleStream)。這意味着我從一個流開始,並希望獲得一個新流,其中舊流的每個元素都會流兩次。所以1,2,3,4,4,5給我們1,1,2,2,3,3,4,4,4,4,5,5。是否有這樣的流操作?雙流

+5

只需注意:另一種方法是創建一個返回每個元素兩次的原始集合(或其他流源)的視圖。我不是說這就是你應該做的,只是它是一種選擇,在某些情況下,視圖方法效果更好。 – biziclop

+0

@biziclop:這實際上可能比'flatMap'解決方案更高效,因爲來自此視圖的流將能夠報告其確切的大小。 –

+1

@TagirValeev它不需要創建'n'中間流。 – biziclop

回答

28

創建一個包含當前元素兩次的內部流和flatMap這個流。

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

如果您想通過n乘元素的數量,您可以創建一個實用的方法像這樣的:

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) 
} 

(但要儘量用一個更好的名字了這種方法,因爲目前的一個可以是不明確的)

用例:

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

輸出:

1 
1 
1 
2 
2 
2 
+2

'repeatEach()'可能會是一個好名字:) –

+1

從數學的角度來看,一個好名字將會是'對角化(流 stream,int length)',因爲映射A-> A^n將x發送給x,...,x)被稱爲對角線嵌入。 –

6

可以爲每個原始元素創建2個分量流和flatMap它:

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

恕我直言,你應該提到靜態導入,比如'Collectors.toList' – fabian

3

這裏是什麼biziclop在評論中描述了一個簡單的例子。

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(); 
        } 
       } 
      }; 
     } 
    }; 
} 

(例如工作在Ideone。)

CW'd因爲它不是我的想法和建議flatMap更直接地回答這個問題。