आप रिकर्सिव flatMap
श्रृंखला का उपयोग कर इसे हल कर सकते हैं।
सबसे पहले हमें मानचित्र मूल्यों से आगे बढ़ने की आवश्यकता है, तो उन्हें ArrayList
पर कॉपी करना बेहतर है (यह गहरी प्रति नहीं है, आपके मामले में यह केवल 0 तत्वों के ArrayList
है, इसलिए अतिरिक्त मेमोरी उपयोग है कम)।
दूसरा, पहले देखी तत्वों का एक उपसर्ग बनाए रखने के लिए, के एक सहायक अपरिवर्तनीय Prefix
वर्ग बना सकते हैं:
List<String> list = new Prefix<>(new Prefix<>(new Prefix<>(null, "a"), "b"), "c")
.addTo(new ArrayList<>()); // [a, b, c];
:
private static class Prefix<T> {
final T value;
final Prefix<T> parent;
Prefix(Prefix<T> parent, T value) {
this.parent = parent;
this.value = value;
}
// put the whole prefix into given collection
<C extends Collection<T>> C addTo(C collection) {
if (parent != null)
parent.addTo(collection);
collection.add(value);
return collection;
}
}
यह बहुत ही सरल अपरिवर्तनीय लिंक्ड सूची जो इस तरह इस्तेमाल किया जा सकता है
इसके बाद, के आंतरिक विधि बना सकते हैं जो चेन flatMaps:
private static <T, C extends Collection<T>> Stream<C> comb(
List<? extends Collection<T>> values, int offset, Prefix<T> prefix,
Supplier<C> supplier) {
if (offset == values.size() - 1)
return values.get(offset).stream()
.map(e -> new Prefix<>(prefix, e).addTo(supplier.get()));
return values.get(offset).stream()
.flatMap(e -> comb(values, offset + 1, new Prefix<>(prefix, e), supplier));
}
रिकर्सन की तरह दिखता है, लेकिन यह अधिक जटिल है: यह खुद को सीधे कॉल नहीं करता है, लेकिन बाहरी विधि को कॉल करने वाले लैम्ब्डा को पास करता है। पैरामीटर:
- मान: मूल मूल्यों के
List
(new ArrayList<>(map.values)
अपने मामले में)।
- ऑफसेट: वर्तमान में इस सूची के भीतर ऑफसेट
- उपसर्ग: लंबाई की वर्तमान उपसर्ग ऑफसेट (या
null
अगर offset == 0
)। इसमें वर्तमान में list.get(0)
, list.get(1)
संग्रह list.get(offset-1)
संग्रह से चयनित तत्व शामिल हैं।
- आपूर्तिकर्ता: परिणामी संग्रह बनाने के लिए फैक्ट्री विधि।
जब हम मान सूची (offset == values.size() - 1
) के अंत तक पहुँच है, हम आपूर्तिकर्ता का उपयोग कर अंतिम संयोजन के मूल्यों से पिछले संग्रह के तत्वों को मैप करें। अन्यथा हम flatMap
का उपयोग करते हैं जो प्रत्येक मध्यवर्ती तत्व उपसर्ग को बढ़ाता है और अगले ऑफसेट के लिए comb
विधि को फिर से कॉल करता है।फिर क्रम बनाए रखने के
Map<String, Collection<String>> map = new LinkedHashMap<>(); // to preserve the order
map.put("A", Arrays.asList("a1", "a2", "a3", "a4"));
map.put("B", Arrays.asList("b1", "b2", "b3"));
map.put("C", Arrays.asList("c1", "c2"));
ofCombinations(map.values(), LinkedHashSet::new).forEach(System.out::println);
हम LinkedHashSet
लिए अलग-अलग संयोजन इकट्ठा:
public static <T, C extends Collection<T>> Stream<C> ofCombinations(
Collection<? extends Collection<T>> values, Supplier<C> supplier) {
if (values.isEmpty())
return Stream.empty();
return comb(new ArrayList<>(values), 0, null, supplier);
}
एक के उपयोग का उदाहरण:
अंत में यहाँ सार्वजनिक विधि इस सुविधा का उपयोग करने के लिए है। आप इसके बजाय किसी अन्य संग्रह का उपयोग कर सकते हैं (उदा। ArrayList::new
)।
आप कुंजी के बारे में परवाह मत करो मैं नक्शा? – durron597
तकनीकी रूप से, परिणाम को कई 'क्लास परिणाम इन्ट्री {स्ट्रिंग कुंजी, मान;}' के रूप में परिभाषित किया गया है, जैसे कि अंतिम परिणाम प्रकार 'सूची <सेट>' प्रकार है, इसलिए हाँ, मुझे चाबियों की परवाह है, हालांकि, मुझे लगा, अगर मुझे क्रमपरिवर्तन की मूल बातें मिलती हैं तो मैं पता लगा सकता हूं कि मैपिंग में कुंजी कैसे काम करें। –
उस मानचित्र कुंजी में आपको कोई समस्या नहीं है, जब तक कि यह 'सॉर्टेड मैप' न हो। इसका मतलब है कि आप नहीं जानते कि आपका उत्तर '{a1, b1, c1}' या '{c1, a1, b1}' या अन्य 4 संभावनाओं से शुरू होगा या नहीं। सवाल अभी भी दिलचस्प है, लेकिन चाबियों के आदेश के बिना, यह कोई सवाल नहीं है जो वास्तविक जीवन में उपयोगी होगा। 'सूची <संग्रह>' का उपयोग करके इनपुट के रूप में अधिक समझ हो सकती है। –
ajb