從 HashMap 中獲取 ArrayList 形式的值和鍵
1. 概述
當我們在 Java 中操作數據結構時,一種常見的情況是從HashMap
中提取值和鍵並將它們組織到ArrayList.
在本快速教程中,我們將探索實現此目標的各種實用方法。
2.問題介紹
首先,我們創建一個HashMap
對像作為輸入示例:
static final HashMap<String, String> DEV_MAP;
static {
DEV_MAP = new HashMap<>();
DEV_MAP.put("Kent", "Linux");
DEV_MAP.put("Eric", "MacOS");
DEV_MAP.put("Kevin", "Windows");
DEV_MAP.put("Michal", "MacOS");
DEV_MAP.put("Saajan", "Linux");
}
如上面的代碼所示,我們使用static
塊初始化了HashMap
。該地圖包含一些開發人員以及他們使用的主要操作系統。
當討論從映射中提取鍵和值列表時,根據特定要求可能會出現不同的場景。
一種這樣的場景涉及原始映射內元素keyList[i]
和valueList[i]
之間的直接關聯(給定索引i
。本質上,鍵和值列表中相應索引處的元素在原始映射的上下文中表現出相關性:
Map:
k1 -> v1
k2 -> v2
k3 -> v3
index : 0, 1, 2
KeyList : k1, k2, k3
ValueList: v1, v2, v3
第二種情況相對簡單。在這裡,我們的目標是從提供的映射中提取鍵列表和值列表,而不保留對初始鍵值對關聯的關注。
本教程將涵蓋這兩種情況。此外,為了確保清晰度和驗證,我們將使用單元測試斷言來驗證每種方法結果的正確性。
3. 使用HashMap
的keySet()
和Values()
方法
首先,讓我們解決更簡單的情況:從DEV_MAP
獲取鍵和值列表,同時忽略 elements 之間的關聯。
Map
接口提供了兩個方法可以讓我們快速解決問題:
-
keySet()
– 從映射中獲取所有鍵作為Set
-
values()
– 將所有值作為Collection
返回
我們可以將Set
和Collection
傳遞給ArrayList
的構造函數來獲取期望的列表對象,例如獲取鍵列表:
List<String> keyList = new ArrayList<>(DEV_MAP.keySet());
assertEquals(Lists.newArrayList("Kent", "Eric", "Kevin", "Michal", "Saajan"), keyList);
然而,運行測試很可能會導致失敗。這是因為**HashMap
不維護其條目的順序**。換句話說,列表中元素的順序無法預測。
接下來,讓我們使用 AssertJ 的containsExactlyInAnyOrder()
來檢查元素並忽略它們的順序:
assertThat(keyList).containsExactlyInAnyOrder("Kent", "Eric", "Kevin", "Michal", "Saajan");
類似地,我們可以使用Map.values()
獲取值列表**:
**
List<String> valueList = new ArrayList<>(DEV_MAP.values());
assertThat(valueList).containsExactlyInAnyOrder("Linux", "MacOS", "Windows", "MacOS", "Linux");
4. 獲取相關的鍵和值列表
現在,讓我們轉向替代方案:獲取鍵列表和值列表,其中元素keyList[i]
和valueList[i]
維護映射內的相關性。
首先,讓我們創建一個方法來驗證這兩個列表是否符合預期:
void assertKeyAndValueList(List<String> keyList, List<String> valueList) {
assertThat(keyList).containsExactlyInAnyOrder("Kent", "Eric", "Kevin", "Michal", "Saajan");
assertThat(valueList).containsExactlyInAnyOrder("Linux", "MacOS", "Windows", "MacOS", "Linux");
for (int i = 0; i < keyList.size(); i++) {
assertThat(DEV_MAP).containsEntry(keyList.get(i), valueList.get(i));
}
}
如上面的方法所示,除了驗證兩個列表是否應包含所需元素外,我們還確保它們在同一索引處的對應元素在DEV_MAP.
解決此問題的一種方法是迭代映射的條目並使用每個條目的鍵和值填充兩個預初始化列表:
List<String> keyList = new ArrayList<>();
List<String> valueList = new ArrayList<>();
for (Map.Entry<String, String> entry : DEV_MAP.entrySet()) {
keyList.add(entry.getKey());
valueList.add(entry.getValue());
}
assertKeyAndValueList(keyList, valueList);
如果我們運行一下,測試就會通過。所以這種方法可以完成工作。
如果我們使用 Java 8 或更高版本,我們可以用forEach()
調用和 lambda 表達式替換for
循環,以提高代碼的可讀性:
List<String> keyList = new ArrayList<>();
List<String> valueList = new ArrayList<>();
DEV_MAP.forEach((k, v) -> {
keyList.add(k);
valueList.add(v);
});
assertKeyAndValueList(keyList, valueList);
5. 結論
在本文中,我們首先討論了該問題的兩種場景:從HashMap.
後來我們探討了每種場景下如何解決問題。
與往常一樣,示例的完整源代碼可在 GitHub 上獲取。