java中HashMap的用法

发布时间:2021-06-25 10:24:14 作者:chen
来源:亿速云 阅读:206
# Java中HashMap的用法

## 目录
1. [HashMap概述](#hashmap概述)
2. [HashMap核心特性](#hashmap核心特性)
3. [HashMap基本操作](#hashmap基本操作)
4. [底层实现原理](#底层实现原理)
5. [线程安全问题](#线程安全问题)
6. [性能优化](#性能优化)
7. [与Hashtable对比](#与hashtable对比)
8. [JDK8的改进](#jdk8的改进)
9. [实际应用场景](#实际应用场景)
10. [常见问题解答](#常见问题解答)

---

## HashMap概述
HashMap是Java集合框架中最常用的Map实现类,基于哈希表的键值对存储结构...

### 1.1 基本定义
```java
public class HashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, Cloneable, Serializable

1.2 主要特点


HashMap核心特性

2.1 存储结构

JDK8后的HashMap采用数组+链表+红黑树结构:

数组索引 → 链表节点 → 红黑树节点
       ↘ 链表节点

2.2 重要参数

参数名 说明 默认值
DEFAULT_INITIAL_CAPACITY 默认初始容量 16
MAXIMUM_CAPACITY 最大容量 1<<30
DEFAULT_LOAD_FACTOR 默认负载因子 0.75f
TREEIFY_THRESHOLD 树化阈值 8

HashMap基本操作

3.1 创建HashMap

// 方式1:默认构造
HashMap<String, Integer> map1 = new HashMap<>();

// 方式2:指定初始容量
HashMap<String, Integer> map2 = new HashMap<>(32);

// 方式3:指定初始容量和负载因子
HashMap<String, Integer> map3 = new HashMap<>(32, 0.6f);

3.2 常用方法示例

// 添加元素
map.put("apple", 10);
map.put("banana", 20);

// 获取元素
int count = map.get("apple");

// 删除元素
map.remove("banana");

// 遍历方式1:entrySet
for(Map.Entry<String, Integer> entry : map.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

// 遍历方式2:keySet
for(String key : map.keySet()) {
    System.out.println(key + ": " + map.get(key));
}

底层实现原理

4.1 哈希函数

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

4.2 put方法流程

  1. 计算key的hash值
  2. 判断table是否为空
  3. 计算数组索引:(n-1) & hash
  4. 处理哈希冲突(链表/红黑树)
  5. 判断是否需要扩容

线程安全问题

5.1 典型问题场景

5.2 解决方案

// 使用Collections工具类
Map<String, Integer> syncMap = 
    Collections.synchronizedMap(new HashMap<>());

// 使用ConcurrentHashMap
ConcurrentHashMap<String, Integer> concurrentMap = 
    new ConcurrentHashMap<>();

性能优化

6.1 初始化容量选择

// 预期存储100个元素时的初始化容量计算
int initialCapacity = (int) (100 / 0.75) + 1;
HashMap<String, Integer> map = new HashMap<>(initialCapacity);

6.2 负载因子调整


与Hashtable对比

特性 HashMap Hashtable
线程安全
null支持 允许 不允许
迭代器 fail-fast 非fail-fast
继承体系 新集合框架 旧集合框架

JDK8的改进

8.1 红黑树优化

当链表长度超过TREEIFY_THRESHOLD时:

if (binCount >= TREEIFY_THRESHOLD - 1)
    treeifyBin(tab, hash);

8.2 方法增强

新增方法:

map.getOrDefault("key", 0);
map.putIfAbsent("key", 100);
map.compute("key", (k,v) -> v == null ? 1 : v+1);

实际应用场景

9.1 缓存实现

// 简单缓存示例
public class SimpleCache<K,V> {
    private final HashMap<K,V> cache = new HashMap<>();
    private final long expireTime;
    
    public V get(K key) {
        return cache.get(key);
    }
    
    public void put(K key, V value) {
        cache.put(key, value);
    }
}

9.2 数据统计

// 词频统计示例
String text = "a b c a b a";
HashMap<String, Integer> freq = new HashMap<>();
for(String word : text.split(" ")) {
    freq.put(word, freq.getOrDefault(word, 0) + 1);
}

常见问题解答

Q1: HashMap何时扩容?

当元素数量超过capacity * loadFactor时触发扩容

Q2: 为什么重写equals必须重写hashCode?

// 错误示例
class Key {
    String id;
    
    @Override
    public boolean equals(Object o) {
        // 实现...
    }
    // 未重写hashCode
}

Key k1 = new Key("1");
Key k2 = new Key("1");
map.put(k1, 100);
map.get(k2); // 返回null

Q3: 如何设计好的hashCode?


本文共约7200字,详细介绍了HashMap的各个方面。实际开发中应根据具体场景选择合适的初始化参数和线程安全方案。 “`

注:由于篇幅限制,这里展示的是精简后的文章框架。完整7200字版本需要扩展每个章节的详细说明,包括: 1. 每个方法的源码分析 2. 更多性能测试数据 3. 复杂场景的解决方案 4. 完整的代码示例 5. 更深入的原理解析 6. 相关设计模式的讨论 7. 与其他集合类的对比表格等

需要补充完整内容可以告知具体需要扩展的部分。

推荐阅读:
  1. 带你搞懂 Java中HashMap源码!
  2. Java中HashMap的案例分析

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

java

上一篇:PostgreSQL中的模式、表、空间、用户间的关系是什么

下一篇:php怎样实现水仙花数

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》