2016-04-09 7 views
8

मैं जावा 8 स्ट्रीम के साथ काम कर रहा हूं, और उन्हें डीबग करने के तरीके के साथ आना चाहूंगा। इसलिए मैंने सोचा कि मैं एक फिल्टर है कि धारा की एक स्तर पर तत्वों मुद्रित, कुछ इस तरह लिख सकते हैं:ट्रेसिंग स्ट्रीम

int[] nums = {3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12}; 
int sum = Arrays.stream(nums) 
    .filter(w -> {System.out.print(" " + w); return true;}) // trace 
    .map(n -> Math.abs(n)) 
    .filter(w -> {System.out.print(" " + w); return true;}) // trace 
    .filter(n -> n % 2 == 0) 
    .distinct() 
    .sum(); 
System.out.println(sum); 

बंद है, लेकिन है कि यह काफी के रूप में यह सुनिश्चित करने के लिए उचित सीमांकक नहीं है नहीं है, यह सुपाठ्य:

3 3 -4 4 8 8 4 4 -2 2 17 17 9 9 -10 10 14 14 6 6 -12 1256 

क्या मैं चाहता हूँ है:

[3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12] 
[3 4 8 4 2 17 9 10 14 6 12] 
56 

वहाँ यह करने के लिए एक अधिक मानक तरीका है? ध्यान दें कि लिंक किए गए आलेख के रूप में पीक कहते हैं कि ऐसा नहीं करता है, क्योंकि मैं किसी भी स्तर पर स्ट्रीम के सभी तत्वों को एक साथ इकट्ठा करना चाहता हूं।

+1

आप 'peek' ऑपरेशन की तलाश में हैं, लिंक किए गए प्रश्न की जांच करें। – Tunaki

+0

पीक नौकरी नहीं करेगा। मैंने अपने प्रश्न के लिए कुछ और विवरण जोड़ा है। यह एक डुप्लिकेट नहीं है! – pitosalas

+1

आह हाँ। लेकिन यह नहीं है कि यह कैसे काम करता है: स्ट्रीम एक एकल पाइपलाइन है। प्रत्येक तत्व इसे तब तक शुरू करता है जब तक इसे खपत नहीं किया जाता है। और अगले के लिए दोहराना। आप जो चाहते हैं उसे प्राप्त करने के लिए, आपको एकाधिक पाइपलाइनों की आवश्यकता होगी। एक संग्रह कॉल पूरी धारा का उपभोग करता है और आप इसे फिर से संसाधित नहीं कर सकते हैं। – Tunaki

उत्तर

9

आपको प्रत्येक चेकपॉइंट के लिए एक अलग सूची का उपयोग करने की आवश्यकता होगी।

आम तौर पर मैं इस तरह से राज्य को म्यूटेट करने के लिए स्ट्रीम ऑपरेशंस का उपयोग करने की अनुशंसा नहीं करता, लेकिन डीबगिंग उद्देश्यों के लिए मुझे लगता है कि यह ठीक है। वास्तव में, जैसा कि @BrianGoetz नीचे बताता है, डीबगिंग कारण peek जोड़ा गया था।

int[] nums = {3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12}; 
List<Integer> checkPoint1 = new ArrayList<>(); 
List<Integer> checkPoint2 = new ArrayList<>(); 
List<Integer> checkPoint3 = new ArrayList<>(); 
List<Integer> checkPoint4 = new ArrayList<>(); 
int sum = Arrays.stream(nums) 
       .peek(checkPoint1::add) 
       .map(n -> Math.abs(n)) 
       .peek(checkPoint2::add) 
       .filter(n -> n % 2 == 0) 
       .peek(checkPoint3::add) 
       .distinct() 
       .peek(checkPoint4::add) 
       .sum(); 
System.out.println(checkPoint1); 
System.out.println(checkPoint2); 
System.out.println(checkPoint3); 
System.out.println(checkPoint4); 
System.out.println(sum); 

आउटपुट:

[3, -4, 8, 4, -2, 17, 9, -10, 14, 6, -12] 
[3, 4, 8, 4, 2, 17, 9, 10, 14, 6, 12] 
[4, 8, 4, 2, 10, 14, 6, 12] 
[4, 8, 2, 10, 14, 6, 12] 
56 
+0

चालाक। ऐसा लगता है कि यह नौकरी करता है। लेकिन थोड़े बदसूरत मुझे यकीन है कि सभी सहमत होंगे। यह शायद सबसे अच्छा हम कर सकते हैं! – pitosalas

+0

यह भयानक है। दुर्भाग्य से इस सामान को डीबग करने का कोई आसान तरीका नहीं है। –

+1

यही कारण है कि हमने 'peek() 'जोड़ा। –

6

आप पाते हैं अपने आप को पौलुस का समाधान बहुत बार फिर एक एक स्थिर आवरण समारोह है कि अनुक्रमित झांकना कार्यों उत्पन्न करता है लिख सकता है की आवश्यकता होगी, तो:

int sum = streamDebugger<Integer>((Supplier<Consumer<?>> peekGen) => { 
    return Arrays.stream(nums) 
       .peek(peekGen.get()) 
       .map(n -> Math.abs(n)) 
       .peek(peekGen.get()) 
       .filter(n -> n % 2 == 0) 
       .peek(peekGen.get()) 
       .distinct() 
       .peek(peekGen.get()) 
       .sum(); 
}) 

स्वचालित करने के लिए यह एक कदम आगे भी पूरे स्ट्रीम इंटरफ़ेस को लपेट सकता है ताकि प्रत्येक परिभाषित इंटरफ़ेस विधि फिर से एक लपेटा हुआ इम्प्लास लौटा दे ementation कि स्वचालित रूप से पाइप लाइन में प्रत्येक चरण के लिए देखना करता है:

int sum = debugIntStream(Arrays.stream(nums)) 
       .map(n -> Math.abs(n)) 
       .filter(n -> n % 2 == 0) 
       .distinct() 
       .sum(); 

के बाद से कार्यान्वयन काफी थकाऊ और उम्मीद है कि आवश्यक नहीं होगा कार्यान्वयन पाठक के लिए छोड़ दिया है।

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