2014-05-16 10 views
6

से दो अलग-अलग आउटपुट प्राप्त करना मैं जावा -8 में नए StreamAPI का परीक्षण कर रहा हूं और 10000 यादृच्छिक सिक्का के परिणाम की जांच करना चाहता हूं। अब तक मेरे पास है:स्ट्रीम

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

यह पहला समाधान इस तथ्य पर भरोसा कर रहा है कि 10 000 सिक्का के सिर और पूंछ की संख्या गिनती एक द्विपदीय कानून का पालन करती है।

इस विशेष उपयोग के मामले के लिए, आप 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

आप आप दो outputs प्राप्त करना चाहते हैं, एक एकल पुनरावृत्ति में कई परिणामों को एकत्र कर सकते हैं। आपके मामले में, यह निम्नानुसार दिखाई दे सकता है:

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> को बॉक्स, के रूप में आप इस उदाहरण में उनके बॉक्स्ड संस्करण में उन्हें भंडारण किया जाएगा किसी भी तरह होगा। और अंत में, पहचान i -> i पर एक groupingBy समारोह है, जो आप एक Map<Integer, List<Integer>> देता है, जो नहीं है कि तुम क्या चाहते हो के साथ उन्हें इकट्ठा इसलिए आप उस पर आपरेशन Collectors.counting(), इस तरह के साथ List<Integer> की जगह है कि List<Integer> एक Long हो जाता है, इसलिए एक में जिसके परिणामस्वरूप Map<Integer, Long>

+1

+1 यह भी एक अच्छा समाधान है :-) –

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