2014-05-16 16 views
6

我正在測試java-8中新的StreamAPI並且想要檢查10000個隨機coinflips的結果。到目前爲止,我有:從流中獲取兩個不同的輸出

public static void main(String[] args) { 

     Random r = new Random(); 
     IntStream randomStream = r.ints(10000,0, 2); 

     System.out.println("Heads: " + randomStream.filter(x -> x==1).count()); 
     System.out.println("Tails: " + randomStream.filter(x -> x==0).count()); 
    } 

但這引發異常:

java.lang.IllegalStateException: stream has already been operated upon or closed 

我明白這是爲什麼happenning但我怎麼可以打印頭和尾巴計數,如果我只能用流一次?

+1

我認爲這個問題已解決(並希望解決)在這個線程http://stackoverflow.com/questions/19803058/java-8-stream-getting-head-and-tail – luanjot

回答

6

這個第一個解決方案是依靠一個事實,即按照二項法則來計算10000個coinflips的正面和反面的數量。

對於這種特殊用例,您可以使用summaryStatistics方法。

Random r = new Random(); 
IntStream randomStream = r.ints(10000,0, 2); 
IntSummaryStatistics stats = randomStream.summaryStatistics(); 
System.out.println("Heads: "+ stats.getSum()); 
System.out.println("Tails: "+(stats.getCount()-stats.getSum())); 


否則,您可以使用 collect操作來創建地圖,將地圖的數量流中出現次數的每一個可能的結果。

Map<Integer, Integer> map = randomStream 
          .collect(HashMap::new, 
            (m, key) -> m.merge(key, 1, Integer::sum), 
            Map::putAll); 
System.out.println(map); //{0=4976, 1=5024} 

最後一個解決方案的優點是,它適用於您爲要生成的隨機整數給出的任何界限。

例子:

IntStream randomStream = r.ints(10000,0, 5); 
.... 
map => {0=1991, 1=1961, 2=2048, 3=1985, 4=2015} 
+0

我可以問問合併是什麼方法? –

1

您可以收集一些結果在一個迭代中,如果你想獲得兩個輸出。在你的情況下,它可能看起來如下:

Random r = new Random(); 
IntStream randomStream = r.ints(10000,0, 2); 

int[] counts = randomStream.collect(
    () -> new int[] { 0, 0 }, // supplier 
    (a, v) -> a[v]++, // accumulator 
    (l, r) -> { l[0] += r[0]; l[1] += r[1]; }); // combiner 

System.out.println("Heads: " + counts[0]); 
System.out.println("Tails: " + counts[1]); 
4

雖然所有其他答案都是正確的,但它們的制定有點麻煩。

Map<Integer, Long>,將翻轉的硬幣映射到計數。

Map<Integer, Long> coinCount = new Random().ints(10000, 0, 2) 
     .boxed() 
     .collect(Collectors.groupingBy(i -> i, Collectors.counting())); 

此將首先創建IntStream,然後將它們框來Stream<Integer>,你會被他們的盒裝版本,無論如何在這個例子中存儲起來。並配有groupingBy功能上的身份i -> i,它給你一個Map<Integer, List<Integer>>,這是不是你想要的最後收集他們,因此你與它的操作Collectors.counting(),如更換List<Integer>List<Integer>成爲Long,從而導致Map<Integer, Long>

+1

+1這也是一個不錯的解決方案:-) –