2016-03-28 6 views
5

मैं Person वस्तुओं का संग्रह है :.जावा 8 एक संग्रह धाराओं और कलेक्टरों का उपयोग कर के उप सूची प्रविष्टियों के लिए मानचित्रण

public class Person { 

    String name; 

    ChildrenListHolder childrenListHolder; 
} 

public class ChildrenListHolder { 
    List<Children> children; 
} 

public class Children { 
    String childrensName; 
} 

(इकाई संरचना तीसरे पक्ष द्वारा दिया जाता है।)

अब, मैं एक Map<String,List<Person>> childrensName जरूरत है -> व्यक्ति-सूची

उदाहरण के लिए (सरलीकृत):

Person father: {name: "John", childrensListHolder -> {"Lisa", "Jimmy"}} 
Person mother: {name: "Clara", childrensListHolder -> {"Lisa", "Paul"}} 
Person george: {name: "George", childrensListHold -> "Paul"}} 

नक्शा, मैं जरूरत

Map<String, List<Person>> map: {"Lisa" -> {father, mother}, 
           "Jimmy" -> {father}, 
           "Paul" -> {mother, george}} 
0 है

मैं के लिए और अगर के एक समूह के साथ ऐसा कर सकते हैं। लेकिन मैं धाराओं और कलेक्टरों का उपयोग करके यह कैसे कर सकता हूं। मैंने कई दृष्टिकोणों की कोशिश की है, लेकिन मुझे अपेक्षित परिणाम नहीं मिल सकते हैं। TIA।

उत्तर

7

को देखते हुए एक List<Person> persons, तो आपको निम्न

Map<String,List<Person>> map = 
    persons.stream() 
      .flatMap(p -> p.childrenListHolder.children.stream().map(c -> new AbstractMap.SimpleEntry<>(c, p))) 
      .collect(Collectors.groupingBy(
      e -> e.getKey().childrensName, 
      Collectors.mapping(Map.Entry::getValue, Collectors.toList()) 
      )); 

यह व्यक्तियों पर एक स्ट्रीम पैदा कर रही है हो सकता है। फिर प्रत्येक व्यक्ति बच्चे को और प्रत्येक बच्चे के लिए व्यक्ति को पकड़े हुए एक टुपल द्वारा मैप किया जाता है। अंत में, हम बच्चे के नाम से समूह करते हैं और सभी व्यक्तियों को एक सूची में एकत्र करते हैं।

public static void main(String[] args) { 
    List<Person> persons = Arrays.asList(
     new Person("John", new ChildrenListHolder(Arrays.asList(new Children("Lisa"), new Children("Jimmy")))), 
     new Person("Clara", new ChildrenListHolder(Arrays.asList(new Children("Lisa"), new Children("Paul")))), 
     new Person("George", new ChildrenListHolder(Arrays.asList(new Children("Paul")))) 
    ); 

    Map<String,List<Person>> map = 
     persons.stream() 
       .flatMap(p -> p.childrenListHolder.children.stream().map(c -> new AbstractMap.SimpleEntry<>(c, p))) 
       .collect(Collectors.groupingBy(
       e -> e.getKey().childrensName, 
       Collectors.mapping(Map.Entry::getValue, Collectors.toList()) 
       )); 

    System.out.println(map); 
} 
+0

धन्यवाद। दुर्भाग्य से यह काम नहीं करता है। flatMap कॉल स्ट्रीम '' देता है, तो 'का उपयोग कर e.getKey' काम नहीं करता है का संग्रह। – t777

+1

@ t777 हम्म मैं सिर्फ ग्रहण Mars.2 अंदर कि कोड भाग गया और यह ठीक काम किया। आप किस आईडीई का उपयोग कर रहे हैं? – Tunaki

+0

मैं ग्रहण लूना 2 का उपयोग कर रहा हूं (4.4.2) – t777

5

मैं ऐसा कर सकते हैं के लिए और अगर के एक समूह के साथ:

नमूना वहाँ संभालने कोड उचित निर्माता ये हैं।

मुझे पता है कि आप एक धारा/कलेक्टरों समाधान के लिए कहा है, लेकिन किसी भी मामले में Map#computeIfAbsent का उपयोग कर पाश के लिए एक नेस्टेड भी ठीक काम करता है:

Map<String, List<Person>> map = new HashMap<>(); 
for(Person p : persons) { 
    for(Children c : p.childrenListHolder.children) { 
     map.computeIfAbsent(c.childrensName, k -> new ArrayList<>()).add(p); 
    } 
} 

और इस नए forEach विधि संग्रह को पेश का उपयोग करके लिखा :

Map<String, List<Person>> map = new HashMap<>(); 
persons.forEach(p -> p.childrenListHolder.children.forEach(c -> map.computeIfAbsent(c.childrensName, k -> new ArrayList<>()).add(p))); 

बेशक यह एक-लाइनर और न ही Tunaki समाधान (+1) में की तरह आसान चलाने योग्य नहीं है, लेकिन यदि आप एक "गुच्छा" की जरूरत नहीं है, तो वह भी प्राप्त करने के लिए है की (और यो आप अस्थायी मानचित्र प्रविष्टियों के उदाहरणों के निर्माण से भी बचें)।

+2

हां यह भी एक अच्छा समाधान है। इसका फायदा यह है कि आपको बच्चों और व्यक्ति को पकड़ने के लिए एक ट्यूपल की आवश्यकता नहीं है। – Tunaki

+0

धन्यवाद। मुझे आपका समाधान भी पसंद है। मेरी इच्छा है, मैं दो जवाब स्वीकार कर सकता हूं। ;) – t777

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