यदि मेरे पास एक है List<List<Object>>
, तो मैं List<Object>
जावा 8 की सुविधाओं का उपयोग करके इसे एक ही पुनरावृत्ति क्रम में सभी वस्तुओं में कैसे बदल सकता हूं ?
यदि मेरे पास एक है List<List<Object>>
, तो मैं List<Object>
जावा 8 की सुविधाओं का उपयोग करके इसे एक ही पुनरावृत्ति क्रम में सभी वस्तुओं में कैसे बदल सकता हूं ?
जवाबों:
आप flatMap
एक ही स्ट्रीम में आंतरिक सूचियों (स्ट्रीम में बदलने के बाद) को समतल करने के लिए उपयोग कर सकते हैं , और फिर एक सूची के परिणाम को इकट्ठा कर सकते हैं:
List<List<Object>> list = ...
List<Object> flat =
list.stream()
.flatMap(List::stream)
.collect(Collectors.toList());
Class::method
पहली बार में थोड़ा अजीब लगता है, लेकिन इसका यह लाभ है कि यह घोषित करता है कि आप किस प्रकार की वस्तु से मैप कर रहे हैं। यह एक ऐसी चीज है जिसे आप अन्यथा धाराओं में खो देते हैं।
flatMap
पर विधि Stream
कर सकते हैं निश्चित रूप से आप के लिए उन सूचियों समतल है, लेकिन यह बनाना होगा Stream
तो एक तत्व के लिए वस्तुओं, Stream
परिणाम के लिए।
आपको उन सभी Stream
वस्तुओं की आवश्यकता नहीं है । यहाँ कार्य करने के लिए सरल, संक्षिप्त कोड है।
// listOfLists is a List<List<Object>>.
List<Object> result = new ArrayList<>();
listOfLists.forEach(result::addAll);
क्योंकि एक List
है Iterable
, यह कोड विधि (जावा 8 सुविधा) को कॉल करता हैforEach
, जिसे विरासत में मिला है Iterable
।
Iterable
जब तक सभी तत्वों को संसाधित नहीं किया जाता है तब तक प्रत्येक तत्व के लिए दी गई कार्रवाई करता है या कार्रवाई एक अपवाद फेंकता है। यदि इसे निर्दिष्ट किया जाता है, तो क्रियाओं को पुनरावृत्ति के क्रम में किया जाता है।
और एक List
के Iterator
अनुक्रमिक क्रम में रिटर्न आइटम नहीं है।
के लिए Consumer
, इस कोड को एक विधि संदर्भ (जावा 8 सुविधा) पूर्व जावा 8 विधि करने के लिए गुजरता List.addAll
भीतरी सूची तत्वों क्रमिक रूप से जोड़ने के लिए।
इस संग्रह के अंत में निर्दिष्ट संग्रह में सभी तत्वों को जोड़ते हैं, इस क्रम में कि वे निर्दिष्ट संग्रह के इट्रेटर (वैकल्पिक संचालन) द्वारा वापस कर दिए जाते हैं।
आप ग्रहण संग्रहflatCollect()
से पैटर्न का उपयोग कर सकते हैं ।
MutableList<List<Object>> list = Lists.mutable.empty();
MutableList<Object> flat = list.flatCollect(each -> each);
यदि आप सूची से नहीं बदल सकते हैं List
:
List<List<Object>> list = new ArrayList<>();
List<Object> flat = ListAdapter.adapt(list).flatCollect(each -> each);
नोट: मैं कलेक्शन एक्लिप्स का योगदानकर्ता हूं।
जैसा कि @ सरवन ने उल्लेख किया है:
फ्लैटमैप बेहतर है लेकिन इसे प्राप्त करने के अन्य तरीके भी हैं
listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
योग करने के लिए, निम्नानुसार ही प्राप्त करने के कई तरीके हैं:
private <T> List<T> mergeOne(Stream<List<T>> listStream) {
return listStream.flatMap(List::stream).collect(toList());
}
private <T> List<T> mergeTwo(Stream<List<T>> listStream) {
List<T> result = new ArrayList<>();
listStream.forEach(result::addAll);
return result;
}
private <T> List<T> mergeThree(Stream<List<T>> listStream) {
return listStream.reduce(new ArrayList<>(), (l1, l2) -> {
l1.addAll(l2);
return l1;
});
}
private <T> List<T> mergeFour(Stream<List<T>> listStream) {
return listStream.reduce((l1, l2) -> {
List<T> l = new ArrayList<>(l1);
l.addAll(l2);
return l;
}).orElse(new ArrayList<>());
}
private <T> List<T> mergeFive(Stream<List<T>> listStream) {
return listStream.collect(ArrayList::new, List::addAll, List::addAll);
}
मैं बस की तरह एक और परिदृश्य व्याख्या करना चाहते हैं List<Documents>
, इस सूची की तरह अन्य दस्तावेजों के कुछ और सूचियों में शामिल है List<Excel>
, List<Word>
, List<PowerPoint>
। तो संरचना है
class A {
List<Documents> documentList;
}
class Documents {
List<Excel> excels;
List<Word> words;
List<PowerPoint> ppt;
}
अब यदि आप केवल दस्तावेजों से एक्सेल को पुनरावृत्त करना चाहते हैं, तो नीचे कुछ ऐसा करें ..
तो कोड होगा
List<Documents> documentList = new A().getDocumentList();
//check documentList as not null
Optional<Excel> excelOptional = documentList.stream()
.map(doc -> doc.getExcel())
.flatMap(List::stream).findFirst();
if(excelOptional.isPresent()){
Excel exl = optionalExcel.get();
// now get the value what you want.
}
मुझे उम्मीद है कि कोडिंग के दौरान यह किसी के मुद्दे को हल कर सकता है ...
हम इसके लिए फ्लैटमैप का उपयोग कर सकते हैं, कृपया नीचे कोड देखें:
List<Integer> i1= Arrays.asList(1, 2, 3, 4);
List<Integer> i2= Arrays.asList(5, 6, 7, 8);
List<List<Integer>> ii= Arrays.asList(i1, i2);
System.out.println("List<List<Integer>>"+ii);
List<Integer> flat=ii.stream().flatMap(l-> l.stream()).collect(Collectors.toList());
System.out.println("Flattened to List<Integer>"+flat);
एरण के उत्तर पर एक विस्तार जो शीर्ष उत्तर था, यदि आपके पास सूचियों की परतों का एक गुच्छा है, तो आप उन्हें सपाट कर सकते हैं।
यह भी छानने का एक आसान तरीका के साथ आता है क्योंकि आप परतों के नीचे जाते हैं यदि आवश्यक हो।
उदाहरण के लिए:
List<List<List<List<List<List<Object>>>>>> multiLayeredList = ...
List<Object> objectList = multiLayeredList
.stream()
.flatmap(someList1 -> someList1
.stream()
.filter(...Optional...))
.flatmap(someList2 -> someList2
.stream()
.filter(...Optional...))
.flatmap(someList3 -> someList3
.stream()
.filter(...Optional...))
...
.collect(Collectors.toList())
यह SQL में SELECT स्टेटमेंट्स में SELECT स्टेटमेंट्स के समान होगा।
विधि एक कन्वर्ट करने के List<List>
लिए List
:
listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
इस उदाहरण को देखें:
public class Example {
public static void main(String[] args) {
List<List<String>> listOfLists = Collections.singletonList(Arrays.asList("a", "b", "v"));
List<String> list = listOfLists.stream().flatMap(List::stream).collect(Collectors.toList());
System.out.println("listOfLists => " + listOfLists);
System.out.println("list => " + list);
}
}
यह प्रिंट करता है:
listOfLists => [[a, b, c]]
list => [a, b, c]
::
:)