2016-04-30 6 views
6

मैं निम्नलिखित डेटा संरचना है -जावा धारा - एक नेस्टेड सूची (एक दूसरे क्रम में सूची) द्वारा groupingBy

छात्रों की सूची है कि प्रत्येक राज्य अमेरिका के एक सूचियों का मानना ​​है कि प्रत्येक शहरों की एक सूची है।

public class Student { 
    private int id; 
    private String name; 
    private List<State> states = new ArrayList<>(); 
} 

public class State { 
    private int id; 
    private String name; 
    private List<City> Cities = new ArrayList<>(); 
} 

public class City { 
    private int id; 
    private String name; 
} 

मैं निम्नलिखित प्राप्त करना चाहता हूं।

Map<String, Students> citiesIdsToStudensList; 

मैं निम्नलिखित

Map<Integer, List<Integer>> statesToStudentsMap = students.stream() 
      .flatMap(student -> student.getStates().stream()) 
      .flatMap(state -> state.getCities().stream()) 
      .collect(Collectors.groupingBy(City::getId, Collectors.mapping(x -> x.getId(), Collectors.toList()))); 

लिखने लेकिन यह मेरे परिणाम मैं चाहता हूँ नहीं मिलता है।

उत्तर

4

स्ट्रीम एपीआई का उपयोग करके, आपको दो बार फ्लैट मैप करना होगा और प्रत्येक मध्यवर्ती छात्र और शहर को एक टुपल में मैप करना होगा जो छात्र को पकड़ने में सक्षम है।

Map<Integer, List<Student>> citiesIdsToStudentsList = 
    students.stream() 
      .flatMap(student -> student.getStates().stream().map(state -> new AbstractMap.SimpleEntry<>(student, state))) 
      .flatMap(entry -> entry.getValue().getCities().stream().map(city -> new AbstractMap.SimpleEntry<>(entry.getKey(), city))) 
      .collect(Collectors.groupingBy(
       entry -> entry.getValue().getId(), 
       Collectors.mapping(Map.Entry::getKey, Collectors.toList()) 
      )); 

हालांकि, यह हो सकता है यहाँ नेस्टेड for छोरों का उपयोग करने के क्लीनर होगा:

Map<Integer, List<Student>> citiesIdsToStudentsList = new HashMap<>(); 
for (Student student : students) { 
    for (State state : student.getStates()) { 
     for (City city : state.getCities()) { 
      citiesIdsToStudentsList.computeIfAbsent(city.getId(), k -> new ArrayList<>()).add(student); 
     } 
    } 
} 

इस का लाभ उठाता है computeIfAbsent मानचित्र को भरने के लिए और एक ही शहर आईडी के साथ प्रत्येक छात्र की एक सूची बनाता है।

+0

बस यह सुनिश्चित करने के लिए, नेस्टेड फॉर-लूप समाधान के बराबर है: छात्रों के लिए। (प्रत्येक - छात्र -> student.getStates()। प्रत्येक (राज्य -> ​​state.getCities() के लिए। (शहर -> शहरों IdsToStudentsList.computeIfAbsent (city.getId(), के -> नया ऐरेलिस्ट <>())। जोड़ें (छात्र)))? – srborlongan

+1

@ एसरबोरोंगन हां, इस मामले में इसका एक ही परिणाम होगा। – Tunaki

0

Tunaki’s answer के अलावा, आप इसे के रूप में

Map<Integer, List<Student>> citiesIdsToStudentsList = 
    students.stream() 
     .flatMap(student -> student.getStates().stream() 
      .flatMap(state -> state.getCities().stream()) 
      .map(state -> new AbstractMap.SimpleEntry<>(student, state.getId()))) 
     .collect(Collectors.groupingBy(
      Map.Entry::getValue, 
      Collectors.mapping(Map.Entry::getKey, Collectors.toList()) 
     )); 

यह तथ्य यह है कि आप ताकि आप उन्हें सीधे वांछित City वस्तुओं के लिए flatMap कर सकते हैं, वास्तव में State वस्तुओं में कोई दिलचस्पी नहीं कर रहे हैं, यदि आप ऐसा इस्तेमाल को आसान बना सकता यह सही पहले flatMap ऑपरेशन के भीतर है। फिर, Map.Entry बनाते समय तुरंत State.getId ऑपरेशन करके, आप वास्तविक collect ऑपरेशन को सरल बना सकते हैं।

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