![](/img/trans.png)
[英]How to convert List<V> into Map<K, List<V>>, with Java 8 streams and custom List and Map suppliers?
[英]Given a map of type Map<K, List<V>>, how to update value within List<V> using Java streams?
我收到了一些 API 的回復,其類型為:
public class Response {
private String role;
private String permission;
// Setters and getters
}
Role
的值可以是"Admin"
、 "User"
等,permission 的值可以是"R-4"
、 "C-44"
等。 "R-"
表示地區, "C-"
表示國家。 所以最初我通過以下方式構造了 Map<String, Set>:
Map<String, Set<String>> initialMap= responseList.stream().collect(
Collectors.groupingBy(Reponse::getRole, HashMap::new,
Collectors.mapping(Reponse::getPermission, Collectors.toSet()))
);
但是對於我的應用程序,我希望 map 是Map<String, Set<Long>>
,它表示角色以及與該角色相關的各個國家。 基本上,我想從 Set 中刪除"R-"
和"C-"
,這是hashmap
的值。 當值類似於"R-4"
時,我想刪除"R-"
並使用在本例中為4
的 id 並將此 id 傳遞到數據庫以獲取List<Long> countries
並將其添加到hashmap
的值中。 當值類似於"C-44"
時,我想刪除"C-"
並將該 id 添加到hashmap
的值中。 一種方法是手動迭代initialMap
的每個條目,然后獲取其對應的Set<String>
值,然后再次迭代Set<String>
以獲取String
值,然后將其轉換為Long
。 我在想有沒有更好的方法來使用 Streams 做到這一點? 我可以直接從我的初始reponseList
構造Map<String, Set<Long>>
嗎?
你可以試試這個
Map<String, Set<String>> initialMap= responseList.stream().collect(
Collectors.groupingBy(Response::getRole, HashMap::new,
Collectors.mapping((Response res) -> Long.parseLong(res.getModifiedPermission()), Collectors.toSet()))
);
getModifiedPermission()
是一個 function 從權限中刪除前綴。
您可以將 static 方法添加到Response
class:
private static long toLong(Response response) {
String[] arr = response.getPermission().split("-");
String str = arr.length == 1 ? arr[0] : arr[1];
return Long.parseLong(str);
}
然后您可以創建一個方法將List
轉換為Map
:
public static Map<String, Set<Long>> toMap(List<Response> response) {
return response.stream().collect(Collectors.groupingBy(Response::getRole,
Collectors.mapping(Response::toLong, Collectors.toSet())));
}
例子:
List<Response> responseList = List.of(
new Response("AAA","R-4"),
new Response("BBB","C-44"),
new Response("CCC","444"));
Map<String, Set<Long>> map = toMap(responseList);
System.out.println(map);
Output:
{AAA=[4], BBB=[44], CCC=[444]}
似乎這里的主要問題不是解析地區/國家/地區的 id,而是結合List<Long>
包含從某些數據庫/存儲庫檢索到的每個 regionId的多個國家/地區 ID,以及來自權限C-###
的單個國家/地區 ID C-###
.
這可以使用 Java 9+ 中提供的Collectors.flatMapping
來解決。 此外,需要將單獨的 function streamOfCountryIDs
實現到 map 響應的權限進入此收集器的Stream<Long>
:
Map<String, Set<Long>> converted = responses.stream()
.collect(Collectors.groupingBy(
Response::getRole,
Collectors.flatMapping(MyClass::streamOfCountryIDs, Collectors.toSet())
));
System.out.println(converted);
// MyClass
private static Stream<Long> streamOfCountryIDs(Response response) {
String permission = response.getPermission().toUpperCase();
if (permission.startsWith("R-")) {
return countryRepo.getCountriesByRegion(Long.parseLong(permission.substring(2)))
.stream();
} else if (permission.startsWith("C-")) {
return Stream.of(Long.parseLong(permission.substring(2)));
}
// log bad permission and return empty stream or throw an exception if needed
System.out.println("Bad permission: '" + permission + "'");
return Stream.empty();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.