![](/img/trans.png)
[英]Java 8 convert Map<K, List<V>> to Map<V, List<K>>
[英]How to convert List<V> into Map<K, List<V>>, with Java 8 streams and custom List and Map suppliers?
將List<V>
轉換為Map<K, List<V>>
很容易。 例如:
public Map<Integer, List<String>> getMap(List<String> strings) {
return
strings.stream()
.collect(Collectors.groupingBy(String::length));
}
但我想用我自己的List
和Map
供應商來做。
我想出了這個:
public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream()
.collect(Collectors.toMap(
String::length,
item -> {List<String> list = new ArrayList<>(); list.add(item); return list;},
(list1, list2) -> {list1.addAll(list2); return list1;},
HashMap::new));
}
問題:有沒有更簡單、更簡潔或更有效的方法來做這件事? 例如,這樣的事情(不起作用):
return strings.stream()
.collect(Collectors.toMap(
String::length,
ArrayList::new,
HashMap::new));
如果我只需要定義List
供應商,而不需要定義Map
供應商呢?
你可以有以下內容:
public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream().collect(
Collectors.groupingBy(String::length, HashMap::new, Collectors.toCollection(ArrayList::new))
);
}
收集器groupingBy(classifier, mapFactory, downstream)
可用於指定需要哪種類型的地圖,方法是將所需地圖的供應商傳遞給mapFactory
。 然后,用於收集分組到同一鍵的元素的下游收集器是toCollection(collectionFactory)
,它可以收集到從給定供應商獲得的集合中。
這確保返回的映射是HashMap
並且每個值中的列表都是ArrayList
。 請注意,如果您想返回 map 和 collection 的特定實現,那么您很可能希望該方法也返回這些特定類型,以便您可以使用它們的屬性。
如果你只想指定一個集合供應商,並保持groupingBy
默認映射,你可以在上面的代碼中省略供應商並使用兩個參數重載:
public Map<Integer, List<String>> getMap(List<String> strings) {
return strings.stream().collect(
Collectors.groupingBy(String::length, Collectors.toCollection(ArrayList::new))
);
}
作為旁注,你可以有一個通用的方法:
public <K, V, C extends Collection<V>, M extends Map<K, C>> M getMap(List<V> list,
Function<? super V, ? extends K> classifier, Supplier<M> mapSupplier, Supplier<C> collectionSupplier) {
return list.stream().collect(
Collectors.groupingBy(classifier, mapSupplier, Collectors.toCollection(collectionSupplier))
);
}
此聲明的優點是您現在可以使用它來獲得ArrayList
的特定HashMap
作為結果,或LinkedLists
的LinkedHashMap
,如果調用者希望的話:
HashMap<Integer, ArrayList<String>> m = getMap(Arrays.asList("foo", "bar", "toto"),
String::length, HashMap::new, ArrayList::new);
LinkedHashMap<Integer, LinkedList<String>> m2 = getMap(Arrays.asList("foo", "bar", "toto"),
String::length, LinkedHashMap::new, LinkedList::new);
但是,在這一點上,直接在代碼中使用groupingBy
可能更簡單......
如果您打算創建類似於Map<property_1, List<property_2>>
的地圖,則可以使用此解決方案:
Map<String, List<String>> ds= requestList.stream().collect(
Collectors.groupingBy(TagRequest::getProperty_1, HashMap::new,
Collectors.mapping(TagRequest::getProperty_2, Collectors.toList()))
);
如果您打算創建類似於Map<property_1, Set<property_2>>
,您可以使用:
Map<String, List<String>> ds= requestList.stream().collect(
Collectors.groupingBy(TagRequest::getProperty_1, HashMap::new,
Collectors.mapping(TagRequest::getProperty_2, Collectors.toSet()))
);
我也有類似的情況。 我是這樣解決的:
Map<String, List<Object>> map = stringList.stream().collect(Collectors.toMap(str -> str, str -> populateList(str)));
而populateList()
是:
private List<Object> populateList(final String str) {
...
....
List<Object> list = // dao.get(str);
return list;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.