2017-07-20 6 views
5

मुझे java.lang.OutOfMemoryError: Java heap space मिला है जब मैं AbstractSpliterator कार्यान्वयन का उपयोग करता हूं, जो अज्ञात आकार की रिपोर्ट करता है।अज्ञात आकार के साथ सारस्पलाइटर कार्यान्वयन आउटऑफमेमरी त्रुटि: जावा हीप स्पेस

इस मामले में मैंने एक वर्ग StreamCollapse परिभाषित किया जो AbstractSpliterator बढ़ाता है और tryAdvance() कार्यान्वयन में आसन्न तत्वों की श्रृंखला विलय करता है। इसके कन्स्ट्रक्टर सुपर कन्स्ट्रक्टर को super(Long.MAX_VALUE, source.characteristics()) कहते हैं।

API documentation के संबंध में मुझे उम्मीद थी कि Long.MAX_VALUE का उपयोग अज्ञात आकार को इंगित करता है। हालांकि, ऐसा लगता है कि यह उस आकार के साथ स्मृति आवंटित करने की कोशिश कर रहा है।

यह उस स्थान को आवंटित करने का प्रयास क्यों कर रहा है? अनुमानित आकार के लिए मुझे किस मूल्य का उपयोग करना चाहिए?

Stream<Integer> nrs = Stream.of(3, 3, 5, 5, 3, 3, 3, 4, 4, 4 ,5 , 5); 
Integer [] expected = {3, 5, 3, 4, 5}; 
Object[] actual = collapse(nrs).toArray(); 
assertEquals(actual, expected); 

और collapse() विधि कार्यान्वयन:

static <T> Stream<T> collapse(Stream<T> source) { 
    return StreamSupport.stream(
      new StreamCollapse<T>(source.spliterator()), false); 
} 

class StreamCollapse<T> extends AbstractSpliterator<T> implements Consumer<T> { 

    private final Spliterator<T> source; 
    private T curr = null; 

    StreamCollapse(Spliterator<T> source) { 
     super(Long.MAX_VALUE, source.characteristics()); 
     this.source = source; 
    } 

    @Override 
    public boolean tryAdvance(Consumer<? super T> action) { 
     T prev = curr; 
     boolean hasNext; 
     while ((hasNext = source.tryAdvance(this)) && curr.equals(prev)) { } 
     if(hasNext) action.accept(curr); 
     return hasNext; 
    } 

    @Override 
    public void accept(T item) { 
     curr = item; 
    } 
} 

उत्तर

7

आप अपने सम्मिश्रित spliterator से विशेषताओं को दूर करना चाहिए, उदाहरण के लिए:

// an unknown spliterator shouldn't having SIZED | SUBSIZED characteristics 
//            v 
super(Long.MAX_VALUE, source.characteristics() & (~(SIZED | SUBSIZED))); 

यहाँ यह एक उदाहरण है परीक्षण

WHEN एक स्प्लिटार्ट या एक SIZED स्प्लिटार्टर है, Spliterator#getExactSizeIfKnown एक सरणी बनाने के लिए स्ट्रीम द्वारा उपयोग किया जाएगा।

Characteristic value signifying that the value returned from estimateSize() prior to traversal or splitting represents a finite size that, in the absence of structural source modification, represents an exact count of the number of elements that would be encountered by a complete traversal.

अगर में समानांतर Stream#toArray इच्छा धारा रन एक IllegalArgumentExceptionअगर estimateSize> = Long.MAX_VALUE - 8 फेंकता है।

यदि धारा एक क्रमिक रूप से है स्ट्रीम Stream#toArray इच्छा estimateSize को अपने आंतरिक सरणी क्षमता बढ़ती है।

+3

यह सही उत्तर है, स्प्लिटरेटर * को 'SIZED' और 'सब्सिड' विशेषताओं को साफ़ करना होगा। एक अतिरिक्त के रूप में, फ़िल्टर स्प्लिटरेटर के अनुमानित आकार के अनुमान के आकार के अनुमान के आकार के अनुमान के आकार के अनुमान के आकार का अनुमान लगाया जाएगा। आखिरकार, वास्तविक आकार शून्य और उस स्रोत आकार के बीच कहीं होगा। इस प्रकार 'फिल्टर' भी यह करता है और वर्तमान कार्यान्वयन पूरी तरह अज्ञात आकारों के मुकाबले बहुत बेहतर होगा। – Holger

+0

@ होल्गर मेरे उत्तर का ऑडिट करने के लिए धन्यवाद। मुझे भी आपका सुझाव मिलता है। –

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