2015-08-28 12 views
5

मैं निम्न स्वरूप में इनपुट स्ट्रिंग्स की एक श्रृंखला है:जावा 8 groupingby

typeA:code1, 
typeA:code2, 
typeA:code3, 
typeB:code4, 
typeB:code5, 
typeB:code6, 
typeC:code7, 
... 

और मैं निम्नलिखित संरचना के साथ एक Map<String, List<String>> प्राप्त करने की आवश्यकता:

typeA, [code1, code2, code3] 
typeB, [code4, code5, code6] 
typeC, [code7, code8, ...] 

पकड़ है कि प्रत्येक प्रकार को उत्पन्न करने के लिए मुझे प्रत्येक इनपुट पर इस तरह के फ़ंक्शन को कॉल करने की आवश्यकता है स्ट्रिंग:

public static String getType(String code) 
{ 
    return code.split(":")[0]; // yes this is horrible code, it's just for the example, honestly 
} 

I ' मुझे पूरा भरोसा है कि स्ट्रीम और कलेक्टर यह कर सकते हैं, लेकिन मैं ऐसा करने के लिए मंत्रों का सही मिश्रण पाने के लिए संघर्ष कर रहा हूं।

उत्तर

8

यहाँ (कक्षा A नाम पर है यह सोचते हैं) एक ही रास्ता यह करने के लिए है:

Map<String, List<String>> result = Stream.of(input) 
          .collect(groupingBy(A::getType, mapping(A::getValue, toList()))); 

यदि आप चाहते हैं उत्पादन आप डिफ़ॉल्ट HashMap के बजाय एक ट्री-मैप का उपयोग कर सकते अनुसार क्रमबद्ध:

.collect(groupingBy(A::getType, TreeMap::new, mapping(A::getValue, toList()))); 

पूर्ण उदाहरण:

public static void main(String[] args) { 
    String input[] = ("typeA:code1," + 
       "typeA:code2," + 
       "typeA:code3," + 
       "typeB:code4," + 
       "typeB:code5," + 
       "typeB:code6," + 
       "typeC:code7").split(","); 

    Map<String, List<String>> result = Stream.of(input) 
        .collect(groupingBy(A::getType, mapping(A::getValue, toList()))); 
    System.out.println(result); 
} 

public static String getType(String code) { 
    return code.split(":")[0]; 
} 
public static String getValue(String code) { 
    return code.split(":")[1]; 
} 
+0

धन्यवाद, यह मेरे साथ आने के करीब है। मुझे एहसास हुआ कि ग्रुपिंग में पहले पैरामीटर का प्रकार एक func है, और मैं वहां अपने GetType फ़ंक्शन का उपयोग कर सकता हूं। – endian

6

अगर आप समझते हैं कि तुम क्या नहीं दिखाए हैं कोड सरल हो जाता है, था टी आप विभाजन स्ट्रिंग के दूसरे भाग के रूप में अच्छी तरह से की जरूरत है:

Map<String, List<String>> result = Stream.of(input).map(s->s.split(":", 2)) 
    .collect(groupingBy(a->a[0], mapping(a->a[1], toList()))); 

(यह मानते हुए कि आपके पास एक import static java.util.stream.Collectors.*;)

एक सरणी में एक String बंटवारे के साथ गलत कुछ भी नहीं है, कार्यान्वयन भी है एक "तेज -पाथ "सामान्य मामले के लिए आप एक जटिल नियमित अभिव्यक्ति के बजाय एक साधारण चरित्र का उपयोग करके विभाजित हो रहे हैं।

+0

धन्यवाद, यह भी एक अच्छा दृष्टिकोण है। – endian

2

हालांकि मैं बहुत धीमी थी, यहां एक MCVE दिखा रहा है कि यह Collectors#groupingBy के साथ कैसे हल किया जा सकता है।

"वर्गीकृत" और "मैपर" को परिभाषित करने के लिए स्पष्ट रूप से अलग-अलग विकल्प हैं। यहां मैं ":" से पहले और बाद में भाग खोजने के लिए बस String#substring का उपयोग कर रहा हूं।

import static java.util.stream.Collectors.groupingBy; 
import static java.util.stream.Collectors.mapping; 
import static java.util.stream.Collectors.toList; 

import java.util.ArrayList; 
import java.util.List; 
import java.util.Map; 
import java.util.Map.Entry; 

public class GroupingBySubstringsTest 
{ 
    public static void main(String[] args) 
    { 
     List<String> strings = new ArrayList<String>(); 
     strings.add("typeA:code1"); 
     strings.add("typeA:code2"); 
     strings.add("typeA:code3"); 
     strings.add("typeB:code4"); 
     strings.add("typeB:code5"); 
     strings.add("typeB:code6"); 
     strings.add("typeC:code7"); 

     Map<String, List<String>> result = strings.stream().collect(
      groupingBy(s -> s.substring(0, s.indexOf(":")), 
       mapping(s -> s.substring(s.indexOf(":")+1), toList()))); 

     for (Entry<String, List<String>> entry : result.entrySet()) 
     { 
      System.out.println(entry); 
     } 
    } 
}