我有一個要求,我想HashMap
根據一個模式組合與多個鍵相關的值。
示例:我在 a 中有以下鍵值對HashMap
:
鑰匙 | 價值 |
---|---|
脫脂fac1 ccy1 | 歐元 |
脫脂 fac1 ccy1rate | 0.15 |
脫脂fac1 ccy2 | 美元 |
脫脂 fac1 ccy2rate | 0.20 |
脫脂 fac2 ccy1 | 英鎊 |
脫脂 fac2 ccy1rate | 0.17 |
現在,如果我們查看 中的鍵HashMap
,它們遵循特定的模式:skim fac1,skim fac2....skim facn,這是資訊的隔離標準。
我想以HashMap<String,List<Map<String,String>>>
下列方式分離和組合資訊:
鑰匙 | 價值 |
---|---|
脫脂 fac1 | 歐元,0.15 |
脫脂 fac2 | 美元,0.20,英鎊,0.17 |
有人可以幫我嗎?
謝謝。
uj5u.com熱心網友回復:
您描述的輸出結構之間存在差異:
HashMap<String,List<Map<String,String>>>
以及表中的預期輸出:
HashMap<String,List<String>>
但是,在這兩種情況下,問題主要在于如何找到要按您的值分組的子字串。獲得它們后,您的問題可以通過使用 a 的單個操作流來解決collect(Collectors.toMap())
。唯一改變的是你如何在List
(Map<String, String>
或簡單地String
)內表示你的價值觀。
這是一個帶有逐步詳細說明的注釋的實作:
public class Main {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>(Map.of(
"skim fac1 ccy1", "EUR",
"skim fac1 ccy1rate", "0.15",
"skim fac1 ccy2", "USD",
"skim fac1 ccy2rate", "0.20",
"skim fac2 ccy1", "GBP",
"skim fac2 ccy1rate", "0.17"
));
//Using a set to have unique keys to group by in the resulting map
Set<String> newKeys = new HashSet<>();
//Checking for each key if its substring is equal to any other key's beginning:
// - if it does, then the substring is collected as a key to group by within the final map
//
// - if it doesn't, then another substring is generated from the previous substring until a matching value is found.
// If no value is found, then the key is collected entirely for the resulting map.
for (String key : map.keySet()) {
//This loop keeps creating substrings of the current key until:
// - the substring matches another key's beginning
// - or no more substrings can be generated
int lastIndex = key.lastIndexOf(" ");
while (lastIndex > 0) {
//Checking if the substring matches the beginning of any key except the current one
String subStr = key.substring(0, lastIndex);
if (map.keySet().stream().anyMatch(s -> !s.equals(key) && s.startsWith(subStr))) {
//If a match is found then the current substring is added to the set and the substring iteration is interrupted
newKeys.add(key.substring(0, lastIndex));
break;
}
//Creating a new substring from the previous substring if no match has been found
lastIndex = key.substring(0, lastIndex).lastIndexOf(" ");
}
//If no substrings of the current key matches the beginning of any other key, then the current key is collected
if (lastIndex < 0) {
newKeys.add(key);
}
}
//Creating the resulting map as a map of lists of maps
Map<String, List<Map<String, String>>> mapRes = map.entrySet().stream()
.collect(Collectors.toMap(
entry -> {
//Looking for the newKey which matches the beginning of the current entry's key.
return newKeys.stream().filter(s -> entry.getKey().startsWith(s)).findFirst().orElseThrow(() -> new RuntimeException("No key found"));
},
entry -> {
//Retrieving, like above, the newKey that will be used to map the current value
String newKey = newKeys.stream().filter(s -> entry.getKey().startsWith(s)).findFirst().orElseThrow(() -> new RuntimeException("No key found"));
//Returning a List with a single entry map.
//The entry's key corresponds to the rest of the substring between newKey and key (the portion of key not matched by newKey).
//while the value remains the original value.
return new ArrayList<>(List.of(Map.of(entry.getKey().substring(newKey.length()).trim(), entry.getValue())));
},
//Handling colliding cases by merging the lists together
(list1, list2) -> {
list1.addAll(list2);
return list1;
}
));
//Printing the resulting map
System.out.println("Map of lists of maps");
for (Map.Entry<String, List<Map<String, String>>> entry : mapRes.entrySet()) {
System.out.println(entry.getKey() " => " entry.getValue());
}
//Creating the resulting map as a map of lists of strings
Map<String, List<String>> mapRes2 = map.entrySet().stream()
.collect(Collectors.toMap(
entry -> {
//Looking for the newKey which matches the beginning of the current entry's key.
return newKeys.stream().filter(s -> entry.getKey().startsWith(s)).findFirst().orElseThrow(() -> new RuntimeException("No key found"));
},
entry -> {
//Returning a List with the original value.
return new ArrayList<>(List.of(entry.getValue()));
},
//Handling colliding cases by merging the lists together
(list1, list2) -> {
list1.addAll(list2);
return list1;
}
));
//Printing the resulting map
System.out.println("\nMap of lists of strings");
for (Map.Entry<String, List<String>> entry : mapRes2.entrySet()) {
System.out.println(entry.getKey() " => " entry.getValue());
}
}
}
這是測驗代碼的鏈接:
https://www.jdoodle.com/iembed/v0/s6e
輸出
顯示了您正在考慮的兩種輸出結構的輸出。
Map of lists of maps
skim fac1 => [{ccy2=USD}, {ccy1=EUR}, {ccy1rate=0.15}, {ccy2rate=0.20}]
skim fac2 => [{ccy1rate=0.17}, {ccy1=GBP}]
Map of lists of strings
skim fac1 => [USD, EUR, 0.15, 0.20]
skim fac2 => [0.17, GBP]
uj5u.com熱心網友回復:
根據我的理解,您想要這樣Map<String, Map<String, String>>
的東西來存盤諸如skim fac1 = {ccy2rate=0.20, ccy1=EUR, ccy2=USD, ccy1rate=0.15}
. 我根據這個輸出模式給出我的建議。
Map<String, String> mainMap = new HashMap<>(Map.of(
"skim fac1 ccy1", "EUR",
"skim fac1 ccy1rate", "0.15",
"skim fac1 ccy2", "USD",
"skim fac1 ccy2rate","0.20",
"skim fac2 ccy1", "GBP",
"skim fac2 ccy1rate", "0.17"
));
String pattern = "(.*?)(\\d )(.*)";
//here considering you will only have pattern like `skim facn ...` , collect distinct `skim facn`values only.
/**
* using pattern we can eaasily identify and group the string.
* if pattern get matched then it will give out put as {skim fac}{n}{rest of the value}
* here we only interested in {skim fac}{2} hence contcatanation of 2 strings
*
*/
List<String> distinctKeys = mainMap.keySet().stream()
.map(Pattern.compile(pattern)::matcher)
.filter(Matcher::matches) //considering only valid matches
.map(m -> m.group(1) m.group(2)) //concatanation of 2 string
.distinct()//to get distinct resultset
.collect(Collectors.toList());
System.out.println(distinctKeys);
Map<String, Map<String, String>> output = new HashMap<>();
for (String key : distinctKeys) {
Map<String, String> temp = new HashMap<>();
//filtering out the required keys for each iterations
List<String> mainKeys = mainMap.keySet().stream().filter(m -> m.startsWith(key))
.collect(Collectors.toList());
for (String mainKey : mainKeys) {
//substring the last part of the key
String lastPart = mainKey.substring(key.length() 1, mainKey.length()).trim();
temp.put(lastPart, mainMap.get(mainKey));
}
output.put(key, temp);
}
for (Map.Entry<String, Map<String, String>> entry : output.entrySet()) {
System.out.println(entry.getKey() " ----> " entry.getValue());
}
輸出
skim fac1 ----> {ccy2rate=0.20, ccy1=EUR, ccy2=USD, ccy1rate=0.15}
skim fac2 ----> {ccy1=GBP, ccy1rate=0.17}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/488817.html