[英]Overwriting values in a HashMap that are in an ArrayList<String>
假設我有一個帶字符串鍵和整數值的HashMap:
map = {cat=1, kid=3, girl=3, adult=2, human=5, dog=2, boy=2}
我想通過將此信息放入另一個HashMap來切換鍵和值。 我知道HashMap不能有重復的鍵,因此我嘗試將信息放入帶有Integer的HashMap中,用於映射到String ArrayList的鍵,這樣我就可以將一個Integer映射到多個字符串:
swap = {1=[cat], 2=[adult, dog, boy], 3=[kid, girl], 5=[human]}
我嘗試了以下代碼:
HashMap<Integer, ArrayList<String>> swap = new HashMap<Integer, ArrayList<String>>();
for (String x : map.keySet()) {
for (int i = 0; i <= 5; i++) {
ArrayList<String> list = new ArrayList<String>();
if (i == map.get(x)) {
list.add(x);
swap.put(i, list);
}
}
}
我的代碼唯一的區別是我沒有將數字5硬編碼到我的索引中; 我有一個方法,在原始的HashMap中找到最高的整數值並使用它。 我知道它工作正常,因為我得到相同的輸出,即使我在那里硬編碼5,我只是沒有包括它來節省空間。
我的目標是能夠使用任何數據集進行“反轉”,否則我只能對值進行硬編碼。 我從上面的代碼得到的輸出是這樣的:
swap = {1=[cat], 2=[boy], 3=[girl], 5=[human]}
正如您所看到的,我的問題是值ArrayList只保留放入其中的最后一個String,而不是收集所有String。 如何使ArrayList存儲每個String,而不僅僅是最后一個String?
使用Java 8,您可以執行以下操作:
Map<String, Integer> map = new HashMap<>();
map.put("cat", 1);
map.put("kid", 3);
map.put("girl", 3);
map.put("adult", 2);
map.put("human", 5);
map.put("dog", 2);
map.put("boy", 2);
Map<Integer, List<String>> newMap = map.keySet()
.stream()
.collect(Collectors.groupingBy(map::get));
System.out.println(newMap);
輸出將是:
{1=[cat], 2=[adult, dog, boy], 3=[kid, girl], 5=[human]}
你正在為每次迭代重新創建arrayList,我無法找到一種方法來使用該邏輯,這是一個很好的方法,但不需要檢查最大整數:
for (Map.Entry<String, Integer> entry : map.entrySet()) {
String key = entry.getKey();
Integer value = entry.getValue();
List<String> get = swap.get(value);
if (get == null) {
get = new ArrayList<>();
swap.put(value, get);
}
get.add(key);
}
最好的方法是迭代原始地圖的密鑰集 。
此外,您必須確保列表存在於目標地圖中的任何鍵:
for (Map.Entry<String,Integer> inputEntry : map.entrySet())
swap.computeIfAbsent(inputEntry.getValue(),()->new ArrayList<>()).add(inputEntry.getKey());
這顯然不是最好的解決方案,但是通過交換內部和外部循環來解決問題的方法與下面所示相同。
Map<String, Integer> map = new HashMap<String, Integer>();
map.put("cat", 1);
map.put("kid", 3);
map.put("girl", 3);
map.put("adult", 2);
map.put("human", 5);
map.put("dog", 2);
map.put("boy", 2);
HashMap<Integer, ArrayList<String>> swap = new HashMap<Integer, ArrayList<String>>();
for (Integer value = 0; value <= 5; value++) {
ArrayList<String> list = new ArrayList<String>();
for (String key : map.keySet()) {
if (map.get(key) == value) {
list.add(key);
}
}
if (map.containsValue(value)) {
swap.put(value, list);
}
}
產量
{1 = [貓],2 = [成人,狗,男孩],3 = [孩子,女孩],5 = [人類]}
我能想到的最好的辦法是使用Map.forEach
法現有的地圖和Map.computeIfAbsent
新地圖的方法:
Map<Integer, List<String>> swap = new HashMap<>();
map.forEach((k, v) -> swap.computeIfAbsent(v, k -> new ArrayList<>()).add(k));
作為旁注,您可以使用菱形運算符<>
來創建新映射(在調用映射的構造函數時,不需要重復鍵和值的類型,因為編譯器會推斷它們)。
作為第二個附注,最好使用接口類型而不是具體類型,包括通用參數類型和實際類型。 這就是我分別使用List
和Map
而不是ArrayList
和HashMap
。
使用groupingBy
在雅各布的答案中,但使用Map.entrySet
以獲得更好的性能,正如Boris所建議的那樣 :
// import static java.util.stream.Collectors.*
Map<Integer, List<String>> swap = map.entrySet()
.stream()
.collect(groupingBy(Entry::getValue, mapping(Entry::getKey, toList())));
這使用了另外兩種Collectors
方法: mapping
和toList
。
如果不是這兩個輔助函數,解決方案可能如下所示:
Map<Integer, List<String>> swap = map.entrySet()
.stream()
.collect(
groupingBy(
Entry::getValue,
Collector.of(
ArrayList::new,
(list, e) -> {
list.add(e.getKey());
},
(left, right) -> { // only needed for parallel streams
left.addAll(right);
return left;
}
)
)
);
或者,使用toMap
而不是groupingBy
:
Map<Integer, List<String>> swap = map.entrySet()
.stream()
.collect(
toMap(
Entry::getValue,
(e) -> new ArrayList<>(Arrays.asList(e.getKey())),
(left, right) -> {
left.addAll(right);
return left;
}
)
);
它接縫你覆蓋將它們添加到已經褶皺的arraylist的值instrad。 試試這個:
HashMap<Integer, ArrayList<String>> swapedMap = new HashMap<Integer, ArrayList<String>>();
for (String key : map.keySet()) {
Integer swappedKey = map.get(key);
ArrayList<String> a = swapedMap.get(swappedKey);
if (a == null) {
a = new ArrayList<String>();
swapedMap.put(swappedKey, a)
}
a.add(key);
}
我沒有時間運行它(抱歉,現在沒有Java編譯器),但應該差不多好:)
您可以在Map
中使用java-8中的新merge
方法:
Map<Integer, List<String>> newMap = new HashMap<>();
map.forEach((key, value) -> {
List<String> values = new ArrayList<>();
values.add(key);
newMap.merge(value, values, (left, right) -> {
left.addAll(right);
return left;
});
});
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.