ZetCode

Java HashMap

最后修改日期:2024年2月21日

在本文中,我们将展示如何使用 Java HashMap 集合。

HashMap 是一个存储键值对的容器。每个键都与一个值相关联。HashMap 中的键必须是唯一的。在其他编程语言中,HashMap 被称为关联数组或字典。HashMap 占用更多内存,因为每个值都有一个键。删除和插入操作花费恒定时间。HashMap 可以存储空值。

HashMap 不维护顺序。

Map.Entry 表示 HashMap 中的一个键值对。HashMapentrySet 返回包含在该映射中的映射的 Set 视图。可以使用 keySet 方法检索键的集合。

HashMap 扩展了 AbstractMap 并实现了 MapMap 提供了方法签名,包括 getputsizeisEmpty

HashMap 构造函数

K 是映射键的类型,V 是映射值的类型。

HashMap 方法

下表提供了一些 HashMap 方法。

修饰符和类型 方法 描述
void clear() 从映射中删除所有映射。
对象 clone() 返回 HashMap 实例的浅拷贝:键和值本身不会被克隆。
V boolean containsKey(Object key) 如果此映射包含指定键的映射,则返回 true。
Set entrySet() 返回包含在此映射中的映射的 Set 视图。
布尔值 isEmpty() 如果此映射为空,则返回 true。
Set keySet() 返回包含在此映射中的键的 Set 视图。
V put(K key, V value) 将新映射添加到映射。
V remove(Object key) 如果存在,则从此映射中删除指定键的映射。
V get(Object key) 返回指定键映射到的值,如果此映射不包含该键的映射,则返回 null。
void forEach(BiConsumeraction) 对此映射中的每个条目执行给定的操作,直到所有条目都已处理完毕或该操作引发异常。
V replace(K key, V value) 仅当指定键当前映射到某个值时,才替换该键的条目。
int size() 返回此映射中的键值映射的数量。
Collection values() 返回包含在此映射中的值的 Collection 视图。

在本文中,我们将使用其中的几种方法。

HashMap 创建

HashMap 使用 new 关键字创建。

Map capitals = new HashMap<>();

我们在尖括号之间指定键和值的类型。由于类型推断,没有必要在声明的右侧提供类型。

put 方法

put 方法用于向映射添加新的映射。

capitals.put("svk", "Bratislava");

第一个参数是键,第二个参数是值。

remove 方法

remove 方法用于从映射中删除一个键值对。

capitals.remove("pol");

参数是要从映射中删除其映射的键。

HashMap 初始化

自 Java 9 以来,我们有用于 HashMap 初始化的工厂方法。

Main.java
import java.util.Map;
import static java.util.Map.entry;

void main() {

    Map colours = Map.of(1, "red", 2, "blue", 3, "brown");
    System.out.println(colours);

    Map countries = Map.ofEntries(
            entry("de", "Germany"),
            entry("sk", "Slovakia"),
            entry("ru", "Russia"));

    System.out.println(countries);
}

该示例使用 Map.ofMap.ofEntries 来初始化哈希映射。这两个工厂方法返回不可修改的映射。

Main.java
import java.util.HashMap;
import java.util.Map;

// up to Java 8
void main() {

    Map countries = new HashMap<>() {
        {
            put("de", "Germany");
            put("sk", "Slovakia");
            put("ru", "Russia");
        }
    };

    System.out.println(countries);
}

在此示例中,我们创建一个可修改的哈希映射。这种初始化方式被称为双括号哈希映射初始化。

size 方法

HashMap 的大小由 size 方法确定。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    int size = capitals.size();

    System.out.printf("The size of the HashMap is %d%n", size);

    capitals.remove("pol");
    capitals.remove("ita");

    size = capitals.size();

    System.out.printf("The size of the HashMap is %d%n", size);
}

在代码示例中,我们创建一个 HashMap 并使用 size 确定其大小。然后,我们删除一些键值对并再次确定其大小。我们将结果打印到控制台。

capitals.put("svk", "Bratislava");
capitals.put("ger", "Berlin");

使用 put,我们将新的键值对添加到 HashMap 中。

int size = capitals.size();

这里我们获取映射的大小。

capitals.remove("pol");
capitals.remove("ita");

使用 remove,我们从映射中删除两个键值对。

The size of the HashMap is 6
The size of the HashMap is 4

get 方法

要从 HashMap 检索值,我们使用 get 方法。它接受一个键作为参数。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    String cap1 = capitals.get("ita");
    String cap2 = capitals.get("svk");

    System.out.println(cap1);
    System.out.println(cap2);
}

在该示例中,我们从映射中检索两个值。

String cap2 = capitals.get("svk");

这里我们获取具有 "svk" 键的值。

clear 方法

clear 方法从 HashMap 中删除所有键值对。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    capitals.clear();

    if (capitals.isEmpty()) {

        System.out.println("The map is empty");
    } else {

        System.out.println("The map is not empty");
    }
}

在该示例中,我们删除所有元素并将映射的大小打印到控制台。

capitals.clear();

我们使用 clear 删除所有键值对。

if (capitals.isEmpty()) {

    System.out.println("The map is empty");
} else {

    System.out.println("The map is not empty");
}

使用 isEmpty 方法,我们检查映射是否为空。

containsKey 方法

如果该映射包含指定键的映射,则 containsKey 方法返回 true。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    String key1 = "ger";
    String key2 = "rus";

    if (capitals.containsKey(key1)) {

        System.out.printf("HashMap contains %s key%n", key1);
    } else {

        System.out.printf("HashMap does not contain %s key%n", key1);
    }

    if (capitals.containsKey(key2)) {

        System.out.printf("HashMap contains %s key%n", key2);
    } else {

        System.out.printf("HashMap does not contain %s key%n", key2);
    }
}

在该示例中,我们检查映射是否包含两个键。

if (capitals.containsKey(key1)) {

    System.out.printf("HashMap contains %s key%n", key1);
} else {

    System.out.printf("HashMap does not contain %s key%n", key1);
}

此 if 语句根据映射是否包含给定的键打印一条消息。

HashMap contains ger key
HashMap does not contain rus key

replace 方法

有一些 replace 方法使程序员能够替换条目。

replace(K key, V value)

仅当指定键当前映射到某个值时,此方法才替换该键的条目。

replace(K key, V oldValue, V newValue)

仅当指定键当前映射到指定值时,此方法才替换该键的条目。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("day", "Monday");
    capitals.put("country", "Poland");
    capitals.put("colour", "blue");

    capitals.replace("day", "Sunday");
    capitals.replace("country", "Russia", "Great Britain");
    capitals.replace("colour", "blue", "green");

    capitals.entrySet().forEach(System.out::println);
}

在该示例中,我们使用 replace 替换映射中的键值对。

capitals.replace("day", "Sunday");

这里我们替换 "day" 键的值。

capitals.replace("country", "Russia", "Great Britain");

在这种情况下,该值不会被替换,因为该键当前未设置为 "Russia"

capitals.replace("colour", "blue", "green");

因为旧值是正确的,所以该值被替换。

country=Poland
colour=green
day=Sunday

将 HashMap 转换为 List

在下一个示例中,我们将 HashMap 条目转换为条目列表。

Main.java
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;

void main() {

    Map<String, String> colours = Map.of(
            "AliceBlue", "#f0f8ff",
            "GreenYellow", "#adff2f",
            "IndianRed", "#cd5c5c",
            "khaki", "#f0e68c"
    );

    Set<Map.Entry<String, String>> entries = colours.entrySet();
    List<Map.Entry<String, String>> mylist = new ArrayList<>(entries);

    System.out.println(mylist);
}

entrySet 返回映射的集合视图,该视图稍后传递给 ArrayList 的构造函数。

使用 forEach 迭代

我们使用 forEach 方法来迭代 HashMap 的键值对。forEach 方法对映射的每个元素执行给定的操作,直到所有元素都已处理完毕或该操作引发异常。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    capitals.forEach((k, v) -> System.out.format("%s: %s%n", k, v));
}

在代码示例中,我们使用 lambda 表达式通过 forEach 迭代 HashMap

capitals.forEach((k, v) -> System.out.format("%s: %s%n", k, v));

使用 forEach,我们迭代映射的所有键值对。

使用增强的 for 循环迭代

可以使用增强的 for 循环来迭代 HashMap

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    for (Map.Entry<String, String> pair: capitals.entrySet()) {

        System.out.format("%s: %s%n", pair.getKey(), pair.getValue());
    }
}

在该示例中,我们使用增强的 for 循环迭代 HashMap

for (Map.Entry<String, String> pair: capitals.entrySet()) {

    System.out.format("%s: %s%n", pair.getKey(), pair.getValue());
}

在每个 for 循环中,一个新的键值对被分配给 pair 变量。


使用类型推断,我们可以稍微缩短代码。

Main.java
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    for (var pair: capitals.entrySet()) {

        System.out.format("%s: %s%n", pair.getKey(), pair.getValue());
    }
}

我们通过在 for 循环中使用 var 关键字来缩短代码。

迭代键

我们可能只想迭代 HashMap 的键。

Main.java
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    Set<String> keys = capitals.keySet();

    keys.forEach(System.out::println);
}

该示例迭代 capitals 映射的键。

Set keys = capitals.keySet();

HashMap 的键通过 keySet 方法检索,该方法返回一个键的 Set。键必须是唯一的;因此,我们有一个 SetSet 是一个不包含重复元素的集合。

keys.forEach(System.out::println);

我们使用 forEach 遍历键的集合。

迭代值

我们可能只想迭代 HashMap 的值。

Main.java
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    Collection<String> vals = capitals.values();

    vals.forEach(System.out::println);
}

该示例迭代 HashMap 的值。

Collection vals = capitals.values();

HashMap 的值通过 values 方法检索。

vals.forEach(System.out::println);

我们使用 forEach 遍历该集合。

过滤 HashMap

可以使用 Java Stream API 的 filter 方法过滤 HashMap

Main.java
import java.util.HashMap;
import java.util.Map;
import java.util.stream.Collectors;

void main() {

    Map<String, String> capitals = new HashMap<>();

    capitals.put("svk", "Bratislava");
    capitals.put("ger", "Berlin");
    capitals.put("hun", "Budapest");
    capitals.put("czk", "Prague");
    capitals.put("pol", "Warsaw");
    capitals.put("ita", "Rome");

    Map<String, String> filteredCapitals = capitals.entrySet().stream()
            .filter(e -> e.getValue().length() == 6)
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

    filteredCapitals.entrySet().forEach(System.out::println);
}

在该示例中,我们过滤映射以仅包含其值的长度等于六的键值对。

czk=Prague
ger=Berlin
pol=Warsaw

映射列表

在下一个示例中,我们有一个映射列表。

Main.java
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

void main() {

    Map<String,Integer> fruits1 = new HashMap<>();
    fruits1.put("oranges", 2);
    fruits1.put("bananas", 3);

    Map<String,Integer> fruits2 = new HashMap<>();
    fruits2.put("plums", 6);
    fruits2.put("apples", 7);

    List<Map<String,Integer>> all = new ArrayList<>();
    all.add(fruits1);
    all.add(fruits2);

    all.forEach(e -> e.forEach((k, v) -> System.out.printf("k: %s v %d%n", k, v)));
}

我们定义两个映射并将它们插入到一个列表中。然后我们使用两个 forEach 循环迭代该列表。

k: oranges v 2
k: bananas v 3
k: plums v 6
k: apples v 7

来源

Java HashMap - 语言参考

在本文中,我们介绍了 Java HashMap 集合。

作者

我叫 Jan Bodnar,是一位充满热情的程序员,拥有丰富的编程经验。自 2007 年以来,我一直在撰写编程文章。到目前为止,我已经撰写了 1,400 多篇文章和 8 本电子书。我拥有超过十年的编程教学经验。

列出所有Java教程