2015-11-21 8 views
6

मैं ऐसी विधि लिखने की कोशिश कर रहा हूं जो सूचियों की सूची में ऑब्जेक्ट के सूचकांक पाता है और समांतरता का लाभ उठाता है। मेरा कोड यहाँ है।सूचियों की सूची में किसी ऑब्जेक्ट को खोजने के लिए धाराओं का उपयोग

// returns [i, j] where lists.get(i).get(j) equals o, or null if o is not present. 
public static int[] indices(List<? extends List<?>> lists, Object o) { 
    return IntStream.range(0, lists.size()) 
        .boxed() 
        .flatMap(i -> IntStream.range(0, lists.get(i).size()).mapToObj(j -> new int[]{i, j})) 
        .parallel() 
        .filter(a -> { 
         System.out.println(Arrays.toString(a));  // For testing only 
         return Objects.equals(o, lists.get(a[0]).get(a[1])); 
        }) 
        .findAny() 
        .orElse(null); 
} 

जब मैं निम्नलिखित कोड चलाने

List<List<String>> lists = Arrays.asList(
     Arrays.asList("A", "B", "C"), 
     Arrays.asList("D", "E", "F", "G"), 
     Arrays.asList("H", "I"), 
     Collections.nCopies(5, "J") 
); 
System.out.println("Indices are " + Arrays.toString(indices(lists, "J"))); 

उत्पादन की तरह

[0, 0] 
[0, 1] 
[0, 2] 
[3, 0] 
[3, 1] 
[3, 2] 
[3, 3] 
[2, 0] 
[3, 4] 
[1, 0] 
[1, 1] 
[2, 1] 
[1, 2] 
[1, 3] 
Indices are [3, 0] 

दूसरे शब्दों में कुछ, खोज जारी है के बाद भी वस्तु पाया गया है है। findAny एक शॉर्ट-सर्किटिंग ऑपरेशन नहीं माना जाता है? मैं क्या खो रहा हूँ? साथ ही, सूचियों की सूची या एक जंजीर सरणी पर पुनरावृत्ति करते समय समांतरता का लाभ उठाने का सबसे अच्छा तरीका क्या है?

संपादित

में @ सोटीरिओस का जवाब विचार के बाद, मैं का उत्पादन मिला

Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 0] 
Thread[main,5,main] [2, 0] 
Thread[main,5,main] [2, 1] 
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 0] 
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 1] 
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 2] 
Thread[ForkJoinPool.commonPool-worker-1,5,main] [1, 3] 
Thread[main,5,main] [0, 0] 
Thread[main,5,main] [0, 1] 
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 1] 
Thread[main,5,main] [0, 2] 
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 2] 
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 3] 
Thread[ForkJoinPool.commonPool-worker-3,5,main] [3, 4] 
Indices are [3, 0] 

सूचना है कि

Thread[ForkJoinPool.commonPool-worker-3,5,main] 

के बाद भी जवाब पाया जाता है खोज जारी है।

+0

इसके बजाय फर्स्ट() का उपयोग करें। –

+0

@TaharBakir यह अभी भी खोज जारी है। –

+1

इसके अलावा, समांतरता कुछ समय ले सकती है इससे पहले कि एक धागा दूसरों को सूचित कर सके कि उन्हें जारी रखने की आवश्यकता नहीं है। –

उत्तर

7

लघु सर्किटिंग संचालन के रूप में ही कुछ तत्व खींच के रूप में यह उनके परिणाम का उत्पादन करने के लिए ले जाता है गारंटी नहीं है। वे ऐसा कर सकते हैं, लेकिन इसकी आवश्यकता नहीं है।

flatMap का वर्तमान कार्यान्वयन ऐसा है कि यह हमेशा सबस्ट्रीम की संपूर्ण सामग्री को डाउनस्ट्रीम को दबाएगा। इसलिए यदि आपकी स्ट्रीम समानांतर नहीं थी, तो आप findAny को संतुष्ट करने के लिए स्ट्रीम के माध्यम से अधिक तत्व प्रवाह कर सकते हैं।

+0

ऐसा प्रतीत होता है कि यह उत्तर सही है, और वह 'flatMap()। फ़िल्टर()। FindAny() 'मूल रूप से शॉर्ट-सर्किटिंग नहीं है। मुझे नहीं पता कि इसे इस तरह क्यों लागू किया जाएगा। –

+1

"शॉर्ट-क्यूरकुइटिंग" का अर्थ केवल यह है कि यह * पूरे स्ट्रीम की जांच करने से पहले समाप्त हो सकता है। यह इससे परे कोई गारंटी नहीं देता है। – Misha

1

ऐसा नहीं है कि यह जारी है, यह है कि यह परिणाम देने और खोजने के लिए पहले से ही सभी प्रकार के धागे भेजे गए हैं और परिणाम लौटने से पहले पूरा होने तक प्रतीक्षा करेंगे।

दूसरे शब्दों में, findAny टर्मिनल ऑपरेशन "थ्रेड" कार्य को कई धागे में सबमिट करेगा। ये कार्य केवल filterPredicate लागू कर रहे हैं और कुछ लौटने पर true लौट रहे हैं। findAny, संभवतः, इनमें से किसी एक के मूल्य को वापस करने के लिए प्रतीक्षा करता है। इसे वास्तव में सबमिट करने के लिए वास्तव में कुछ भी रद्द करने का कोई तरीका नहीं है और ऐसा लगता है कि यह कार्यान्वयन पूरे बैच रिटर्न तक अवरुद्ध होगा। यह केवल भविष्य के बैचों को सबमिट करना बंद कर सकता है।

आप वर्तमान धागा प्रवेश करके यह सत्यापित कर सकते हैं:

System.out.println(Thread.currentThread() + " " + Arrays.toString(a)); // For testing only 
+0

मैं आधा सो रहा हूं, इसलिए यह शायद एक बेवकूफ सवाल है, लेकिन यदि कार्यकर्ता धागे का भार आगे बढ़ता है, और पूरी विधि तब तक वापस नहीं आ सकती जब तक कि वे सब खत्म नहीं हो जाते हैं, शॉर्ट सर्किटिंग का मतलब क्या है? –

+1

@PaulBoddington मुझे नहीं लगता कि यह _all_ है, मुझे लगता है कि यह कुछ सबसेट है। –

+1

@PaulBoddington उदाहरण के लिए, मैं 5 धागे को खोजने के लिए आग लगाना। सभी 5 परिणाम लौटा सकते हैं। लेकिन मुझे तय करने से पहले मुझे सभी 5 इंतजार करना होगा। (ठीक है आपको वास्तव में केवल एक के लिए इंतजार करना है, लेकिन आप दूसरों को रद्द नहीं कर सकते हैं। और यह कार्यान्वयन उन सभी 5 कार्यों में शामिल होना चाहता है।) –

2

"इस तरह इसे क्यों लागू किया गया था" के लिए। स्ट्रीम एपीआई कार्यान्वयन में समस्या गहराई से है। flatMap शरीर अक्सर कुछ मध्यवर्ती संचालन (जैसे .flatMap(list -> list.stream().map(...).filter(...))) के साथ एक धारा बनाता है। कोई flatMap कार्यान्वयन stream.spliterator() के अंदर उपयोग कर सकता है और रद्दीकरण का अनुरोध होने तक tryAdvance पर कई बार कॉल कर सकता है। हालांकि spliterator() कॉल कुछ हद तक कृत्रिम स्प्लिटरेटर देता है जब स्ट्रीम में मध्यवर्ती परिचालन होते हैं (यदि नहीं, तो यह केवल मूल स्ट्रीम स्प्लिटरेटर देता है)।यह कृत्रिम स्प्लिटरेटर tryAdvance() कार्यान्वयन बहुत प्रभावी नहीं है, इसलिए इस कार्यान्वयन का उपयोग पूरे फ्लैट मैप किए गए स्ट्रीम की तुलना में खराब प्रदर्शन दोष के रूप में माना जा सकता है। कई मामलों में आप कुछ छोटी धाराओं के लिए flatMap, तो यहां आपके वर्तमान कार्यान्वयन के लिए एक प्रदर्शन लाभ धन्यवाद हो सकता है।

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

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