首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

HashMap中非常好用又经常被忽略的方法

说到HashMap我们再熟悉不过了,写代码的时候几乎天天用。今天就把HashMap中的方法撸一撸,看看还有哪些好用又被我们遗漏的方法。

一、HashMap常用方法

在 HashMap 中,常用的一些方法包括插入、删除、查找等操作。下面通过具体的代码示例来说明这些方法的使用:

import java.util.HashMap;

public class HashMapExample {

public static void main(String[] args) {

// 创建一个 HashMap

HashMap<String, Integer> map = new HashMap<>();

// 1. put() - 插入元素

map.put("apple", 1);

map.put("banana", 2);

map.put("cherry", 3);

System.out.println("After put: " + map);

// 2. get() - 根据 key 查找元素

int value = map.get("apple");

System.out.println("Value for key 'apple': " + value);

// 3. containsKey() - 检查 key 是否存在

boolean hasKey = map.containsKey("banana");

System.out.println("Contains key 'banana': " + hasKey);

// 4. containsValue() - 检查 value 是否存在

boolean hasValue = map.containsValue(3);

System.out.println("Contains value 3: " + hasValue);

// 5. remove() - 删除 key-value 对

map.remove("cherry");

System.out.println("After remove 'cherry': " + map);

// 6. size() - 获取 HashMap 的大小

int size = map.size();

System.out.println("Size of the map: " + size);

// 7. isEmpty() - 检查 HashMap 是否为空

boolean isEmpty = map.isEmpty();

System.out.println("Is the map empty? " + isEmpty);

// 8. keySet() - 获取所有的 key

System.out.println("All keys: " + map.keySet());

// 9. values() - 获取所有的 value

System.out.println("All values: " + map.values());

// 10. entrySet() - 获取所有的键值对

System.out.println("All entries: " + map.entrySet());

// 11. clear() - 清空 HashMap

map.clear();

System.out.println("After clear: " + map);

}

}

详细说明:

put(K key, V value):插入一个键值对到 HashMap 中。如果键已经存在,则更新其对应的值。

get(Object key):根据给定的键返回对应的值。如果键不存在,返回 null。

containsKey(Object key):判断 HashMap 中是否包含指定的键。

containsValue(Object value):判断 HashMap 中是否包含指定的值。

remove(Object key):根据键移除相应的键值对。

size():返回 HashMap 中的键值对数量。

isEmpty():判断 HashMap 是否为空。

keySet():返回所有键的集合(Set 类型)。

values():返回所有值的集合(Collection 类型)。

entrySet():返回所有键值对的集合(Set<Map.Entry<K, V>> 类型)。

clear():清空 HashMap 中的所有键值对。

这些方法我们闭着眼睛都能写出来,但还有一些好用又没有被我们发现的方法。

二、HashMap常常被忽视的好方法

putIfAbsent(K key, V value):

作用:如果指定的键还没有对应的值,那么将键值对插入到 HashMap 中。如果键已经存在,不会进行覆盖操作。

示例:

map.putIfAbsent("apple", 10); // 如果 "apple" 存在,则不更新

System.out.println("After putIfAbsent: " + map);

replace(K key, V value):

作用:替换指定键的值,如果键存在的话。与 put 不同的是,replace 不会在键不存在时插入新值。

示例:

map.replace("banana", 20); // 如果 "banana" 存在,替换其值

System.out.println("After replace: " + map);

replace(K key, V oldValue, V newValue):

作用:当且仅当键存在且其当前值等于 oldValue 时,才会替换为 newValue。

示例:

map.replace("banana", 2, 20); // 如果 "banana" 的值是 2,则替换为 20

System.out.println("After conditional replace: " + map);

getOrDefault(Object key, V defaultValue):

作用:返回与指定键关联的值;如果键不存在,则返回默认值 defaultValue。

示例:

int value = map.getOrDefault("orange", 0); // 如果 "orange" 不存在,返回 0

System.out.println("Value for key 'orange' (or default): " + value);

merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction):

作用:将键和值合并。如果键不存在,将该键和值插入。如果键存在,将现有值与新值使用 remappingFunction 合并。

示例:

map.merge("apple", 5, Integer::sum); // 如果 "apple" 存在,合并值 (加法)

System.out.println("After merge: " + map);

compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):

作用:根据键和当前值计算新的值。可以在操作的过程中自定义修改键值对的逻辑。

示例:

map.compute("apple", (k, v) -> (v == null) ? 1 : v * 2); // 如果 "apple" 存在,值翻倍;否则插入 1

System.out.println("After compute: " + map);

computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction):

作用:如果键不存在,则根据 mappingFunction 计算一个值,并将其插入到 HashMap 中。如果键已经存在,不会修改值。

示例:

map.computeIfAbsent("orange", k -> 4); // 如果 "orange" 不存在,插入 4

System.out.println("After computeIfAbsent: " + map);

computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction):

作用:如果键存在,则计算新的值,并更新该键。如果计算结果为 null,则移除该键。

示例:

forEach(BiConsumer<? super K, ? super V> action):

作用:对 HashMap 中的每一个键值对执行指定的动作。这对于遍历和批量操作非常方便。

示例:

map.forEach((k, v) -> System.out.println(k + " : " + v)); // 遍历并输出所有键值对

10. remove(Object key, Object value):

作用:仅当当前 HashMap 中的键与给定的值匹配时,才移除指定的键值对。如果移除成功返回 true,否则返回 false。

示例:

boolean removed = map.remove("banana", 2); // 只有当 "banana" 的值为 2 时,移除它

System.out.println("Removed 'banana' with value 2: " + removed);

11.putAll(Map<? extends K, ? extends V> paramMap):

作用:将给定的paramMap合并到当前集合。

示例:

// 创建第一个 HashMap

Map<String, Integer> fruitPrices = new HashMap<>();

fruitPrices.put("Apple", 100);

fruitPrices.put("Banana", 50);

fruitPrices.put("Cherry", 200);

// 创建第二个 HashMap

Map<String, Integer> moreFruitPrices = new HashMap<>();

moreFruitPrices.put("Orange", 80);

moreFruitPrices.put("Peach", 120);

// 使用 putAll 方法将第二个 map 中的所有元素添加到第一个 map 中

fruitPrices.putAll(moreFruitPrices);

System.out.println("All entries: " + fruitPrices.entrySet());

12. replaceAll(BiFunction<? super K, ? super V, ? extends V> paramBiFunction):

作用:对 HashMap 中的每个键值对进行遍历,并根据提供的 BiFunction(一个接受两个参数并返回一个结果的函数)对值进行替换。

示例:

// 创建 HashMap 并添加一些商品和价格

Map<String, Integer> productPrices = new HashMap<>();

productPrices.put("Laptop", 1000);

productPrices.put("Phone", 500);

productPrices.put("Tablet", 300);

// 使用 replaceAll 方法对所有价格进行 10% 的折扣

productPrices.replaceAll((product, price) -> price - (price * 10 / 100));

// 输出更新后的商品价格

System.out.println("Discounted product prices:");

for (Map.Entry<String, Integer> entry : productPrices.entrySet()) {

System.out.println(entry.getKey() + ": " + entry.getValue());

}

三、重温三种遍历方式

entrySet().iterator():

作用:返回一个 Iterator,可以用来遍历 HashMap 中的键值对。这是用来逐个遍历和操作元素的有效方式。

示例:

keySet().iterator():

作用:返回一个 Iterator,用于遍历所有的键。可以用来遍历 HashMap 的所有键而不直接访问值。

示例:

values().iterator():

作用:返回一个 Iterator,用于遍历所有的值。适合只关注 HashMap 的值时使用。

示例:

四、不常用方法

clone():

作用:创建并返回此 HashMap 实例的浅表副本。副本包含与原始映射相同的键和值,但键和值本身不会被深复制(也就是说,复制的仅是引用,非对象本身)。

示例:

equals(Object o):

作用:比较指定对象与此 HashMap 是否相等。如果两个 HashMap 包含相同的键值对,则返回 true。

示例:

hashCode():

作用:返回此 HashMap 的哈希码值。hashCode 依赖于 HashMap 中所有键值对的哈希值。

示例:

五、其他特性

负载因子(Load Factor):

HashMap 在超过其容量的一定比例(默认是 0.75)时,会进行动态扩展。较高的负载因子允许更多的元素存储在较小的空间内,但会降低查询效率;较低的负载因子增加了查询效率,但会消耗更多的内存。我们可以通过构造函数自定义初始容量和负载因子:

线程安全性:

HashMap 是非线程安全的,多个线程同时操作时可能会出现并发问题。对于线程安全的版本,可以使用 Collections.synchronizedMap() 包装 HashMap:

通过这些方法和特性,HashMap 提供了极大的灵活性和效率,适用于多种应用场景。

3.性能相关特性

动态扩展:当 HashMap 中的元素数量超过当前容量与负载因子的乘积时,它会进行扩容操作。这意味着哈希表会重新分配更多的桶来存储元素,从而保持较好的查找性能。

时间复杂度:大多数情况下,HashMap的查找、插入和删除操作的时间复杂度是O(1),但在最坏情况下(所有元素都被哈希到相同的桶中),时间复杂度可能会退化为O(n)。

工欲善其事必先利其器,通过整理这些方法,希望我们可以更灵活地使用 HashMap,减少不必要轮子的发明,在不同的应用场景中灵活地调整其性能或功能。

  • 发表于:
  • 原文链接https://page.om.qq.com/page/OpoKCZ76U2sFQLTcQ-61psXw0
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券