java-Map

每日一言

正因为没有翅膀,人们才会寻找飞翔的方法。

——《排球少年》

HashMap

HashMap 类位于 java.util 包中,使用前需要引入:

1
import java.util.HashMap; // 引入 HashMap 类

创建一个HashMap,我们需要传入key和value的数据类型:

1
HashMap<Integer, String> Sites = new HashMap<Integer, String>();
  • HashMap中依旧需要使用包装类

创参数

  1. initialCapacity(初始容量):

    • 含义:指定HashMap内部哈希表(数组)的初始大小
    • 目的 : 如果预先知道大概要存储多少个键值对,设置一个合适的初始容量可以减少 HashMap 在后续添加元素时进行扩容(resize/rehash)的次数。扩容操作是比较耗时的,因为它需要创建一个更大的数组,并将所有现有元素重新计算哈希和位置放入新数组。
    • 默认值:可以不指定,默认为16
    • 注意事项:HashMap的实际容量是2的幂次方。如果你提供的 initialCapacity 不是2的幂,HashMap会将其调整为大于等于你提供的值的最小的2的幂次方。
  2. loadFactor(加载因子):

    • 含义:一个介于0.0 到 1.0 之间的浮点数,它决定了HashMap在其容量达到多大比例时进行扩容。

    • 目的 : 控制空间利用率和查找时间之间的平衡。

      • 较高的加载因子 (例如 0.9):意味着 HashMap 会等到内部数组填充得更满时才扩容。这可以节省空间,但会增加哈希冲突的可能性,从而可能降低查找、插入、删除的平均性能(因为链表或红黑树会更长/更深)。
      • 较低的加载因子 (例如 0.5):意味着 HashMap 在内部数组还比较空的时候就会扩容。这会占用更多空间(因为数组更大),但能减少哈希冲突,从而可能提高平均性能。
    • 默认值 : 如果不指定,默认为 0.75f。这个值通常在时间和空间成本之间提供了一个较好的折衷。

    • 计算扩容阈值:扩容发送在HashMap中的元素超过 capacity*loadFactor 时。

常用方法

添加键值对

1
2
3
4
5
6
7
8
9
10
// 2. 添加键值对 (put)
studentScores.put("Alice", 95);
studentScores.put("Bob", 88);
studentScores.put("Charlie", 92);
studentScores.put("David", 76);

// 如果键已存在,put 会覆盖旧值,并返回旧值
Integer oldScoreBob = studentScores.put("Bob", 90); // Bob's score updated to 90
System.out.println("Bob's old score: " + oldScoreBob); // 输出: Bob's old score: 88
System.out.println("Current map: " + studentScores); // 输出: Current map: {David=76, Alice=95, Bob=90, Charlie=92} (顺序不保证)

获取值

1
2
3
4
5
6
7
// 3. 获取值 (get)
Integer aliceScore = studentScores.get("Alice");
System.out.println("Alice's score: " + aliceScore); // 输出: Alice's score: 95

// 如果键不存在,get 返回 null
Integer frankScore = studentScores.get("Frank");
System.out.println("Frank's score: " + frankScore); // 输出: Frank's score: null

检查键或值是否存在

1
2
3
4
5
6
// 4. 检查键或值是否存在 (containsKey / containsValue)
boolean hasAlice = studentScores.containsKey("Alice");
System.out.println("Contains key 'Alice'? " + hasAlice); // 输出: Contains key 'Alice'? true

boolean hasScore100 = studentScores.containsValue(100);
System.out.println("Contains value 100? " + hasScore100); // 输出: Contains value 100? false

删除键值对

1
2
3
4
// 5. 删除键值对 (remove)
Integer removedScore = studentScores.remove("David"); // 返回删除键的值
System.out.println("Removed David's score: " + removedScore); // 输出: Removed David's score: 76
System.out.println("Map after removing David: " + studentScores); // 输出: Map after removing David: {Alice=95, Bob=90, Charlie=92}

获取Map大小

1
2
3
// 6. 获取 Map 大小 (size)
int size = studentScores.size();
System.out.println("Map size: " + size); // 输出: Map size: 3

检查是否为空

1
2
3
// 7. 检查是否为空 (isEmpty)
boolean isEmpty = studentScores.isEmpty();
System.out.println("Is map empty? " + isEmpty); // 输出: Is map empty? false

遍历Map

keySet()

keySet() 方法返回一个 Set<K> 其中K是HashMap中键的类型。这个Set<>包含HashMap中当前存储的所有键。

关键特性:

  • 视图(View):返回的Set是HashMap 的一个视图,而不是一个独立的副本。
    • 对map的更改会反应在Set中。
    • 对Set的更改(仅限删除)会反应在Map中。
    • 不支持添加:尝试添加会抛出异常。
  • 无序(对于HashMap):Set中的键不保证任何特定的顺序,如果你需要有序的键集合, 应该使用 LinkedHashMapTreeMap

使用keySet()遍历Map的方法如下:

1
2
3
4
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}

values()

HashMap的values()方法返回一个 java.util.Collection<V> ,其中V是Map中Value的类型。这个Collection 包含当前所存储的所有值。

关键特性:

  • 返回类型是一个实现了Collection接口的实例,而不是具体的List或Set.
    • 可能包含重复值
    • 通常无序
  • 视图:
    • 对Map的修改会反映在Collection中。
    • 对Collection的更改(仅限删除)会反映在Map中,会删除所有对应值的键。
    • 不支持添加。

返回所有value的值:

1
2
3
4
// 输出 key 和 value
for (Integer i : Sites.keySet()) {
System.out.println("key: " + i + " value: " + Sites.get(i));
}

HashMap常用方法

方法 描述
clear() 删除 hashMap 中的所有键/值对
clone() 复制一份 hashMap
isEmpty() 判断 hashMap 是否为空
size() 计算 hashMap 中键/值对的数量
put() 将键/值对添加到 hashMap 中
putAll() 将所有键/值对添加到 hashMap 中
putIfAbsent() 如果 hashMap 中不存在指定的键,则将指定的键/值对插入到 hashMap 中。
remove() 删除 hashMap 中指定键 key 的映射关系
containsKey() 检查 hashMap 中是否存在指定的 key 对应的映射关系。
containsValue() 检查 hashMap 中是否存在指定的 value 对应的映射关系。
replace() 替换 hashMap 中是指定的 key 对应的 value。
replaceAll() 将 hashMap 中的所有映射关系替换成给定的函数所执行的结果。
get() 获取指定 key 对应对 value
getOrDefault() 获取指定 key 对应对 value,如果找不到 key ,则返回设置的默认值
forEach() 对 hashMap 中的每个映射执行指定的操作。
entrySet() 返回 hashMap 中所有映射项的集合集合视图。
keySet() 返回 hashMap 中所有 key 组成的集合视图。
values() 返回 hashMap 中存在的所有 value 值。
merge() 添加键值对到 hashMap 中
compute() 对 hashMap 中指定 key 的值进行重新计算
computeIfAbsent() 对 hashMap 中指定 key 的值进行重新计算,如果不存在这个 key,则添加到 hashMap 中
computeIfPresent() 对 hashMap 中指定 key 的值进行重新计算,前提是该 key 存在于 hashMap 中。

LinkedHashMap

LinkedHashMap = HashMap + 维护插入顺序的双向链表

在使用区别上,LinkedHashMap可以以插入顺序遍历Map。使用方法与HashMap一致。

TreeMap

TreeMap是 Java 集合框架中 Map接口的另一个重要实现。它的核心特点是能够 根据键(Key)的顺序来存储和访问键值对

  • 它保证了 Map 中的条目(Entries)总是按照键的 自然顺序 (natural ordering)或者在创建 Map 时提供的 Comparator进行排序。
  • 不允许null键,而允许null值

TreeMap也实现了Map接口,所以对于Map部分的操作方法与HashMap一致。

此外还实现了SortedMap和NavigableMap接口,这些部分这里不再深入,可以自行去了解。


java-Map
http://blog.ulna520.com/2025/04/27/java-Map_20250427_223629/
Veröffentlicht am
April 27, 2025
Urheberrechtshinweis