hashmap
- 1、hashmap 与 hashtable 的区别
- 2、hashmap
- 基本类型与包装类
- 常用实现
- 变量介绍
- 初始容量和负载因子
- 红黑树和链表转化
- HashMap的内部数据结构
- HashMap内部哈希算法
- 参考文章
1、hashmap 与 hashtable 的区别
- 线程安全
- null值
- 执行效率
2、hashmap
hashmap是java中常用的集合类之一,
- 继承自AbstractMap类,实现了 Map、Cloneable、java.io.Serializable 接口。
- 使用哈希表来存储键值对(key-value),通过将键值映射成哈希码来进行高效的插入、删除操作。
- 具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
java.lang.Objectjava.util.AbstractMap<K,V>java.util.HashMap<K,V>
Type Parameters:K - the type of keys maintained by this mapV - the type of mapped values
All Implemented Interfaces:Serializable, Cloneable, Map<K,V>
Direct Known Subclasses:LinkedHashMap, PrinterStateReasonspublic class HashMap<K,V>
extends AbstractMap<K,V>
implements Map<K,V>, Cloneable, Serializable
基本类型与包装类
HashMap 中的元素实际上是对象,一些常见的基本类型可以使用它的包装类。
基本类型对应的包装类表如下:
基本类型 | 引用类型 |
---|---|
boolean | Boolean |
byte | Byte |
short | Short |
int | Integer |
long | Long |
float | Float |
double | Double |
char | Character |
常用实现
1、创建
import java.util.HashMap; // 引入 HashMap 类
HashMap<Integer, String> A = new HashMap<Integer, String>();
2、添加元素
put() 方法:
当调用put方法的时候,先通过hashCode() 获取key 的hashCode,然后找到bucket位置,将Entry对象 存储到bucket上面。
public class Test {public static void main(Strings[] args) {// 创建 HashMap 对象 AHashMap<Integer, String> A = new HashMap<Integer, String>();// 添加键值对A.put(1, "apple");A.put(2, "banana");System.out.println(A);}
}
3、访问元素
get(key) 方法:
通过get(key)获取对象时,也是通过hashCode()方法 获取key的hashCode,然后得到Entry对象。
public class Test{public static void main(String[] args) {// 创建 HashMap 对象 AHashMap<Integer, String> A = new HashMap<Integer, String>();// 添加键值对A.put(1, "apple");A.put(2, "banana");// 访问System.out.println(A.get(1));}
}
4、删除元素
remove(key)方法:
public class Test{public static void main(String[] args) {// 创建 HashMap 对象 AHashMap<Integer, String> A = new HashMap<Integer, String>();// 添加键值对A.put(1, "apple");A.put(2, "banana");// 删除A.remove(1);}
}
5、删除所有元素
clear()方法
6、计算 HashMap 中元素的数量
size() 方法
7、 遍历
- 可以使用 for-each 来迭代 HashMap 中的元素
- 只想获得 key ,使用 KeySet() 方法,然后通过 get(key) 获取对应的 value
- 指向获得value,有getValue() 方法.
// 方法一:Iterator iterator = hashMap.keySet().iterator();while (iterator.hasNext()){String key = (String)iterator.next();System.out.println(key+"="+hashMap.get(key));}
// 方法二:Iterator iterator1 = hashMap.entrySet().iterator();while (iterator1.hasNext()){Map.Entry entry = (Map.Entry) iterator1.next();String key = (String) entry.getKey();Integer value = (Integer) entry.getValue();System.out.println(key+"="+value);}
变量介绍
该类提供了四种构造方法:
HashMap()
Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).HashMap(int initialCapacity)
Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75).HashMap(int initialCapacity, float loadFactor)
Constructs an empty HashMap with the specified initial capacity and load factor.HashMap(Map<? extends K,? extends V> m)
Constructs a new HashMap with the same mappings as the specified Map.
HashMap的内部变量:
int DEFAULT_INITIAL_CAPACITY = 1 << 4
内部哈希表初始容量,值为16,值必须是2的幂次方
int MAXIMUM_CAPACITY = 1 << 30
哈希表最大容量,一般情况下只要内存够用,哈希表不会出现问题
float DEFAULT_LOAD_FACTOR = 0.75f
默认的负载因子,因此初始情况下,当键值对的数量大于 16 * 0.75 = 12 时,就会触发扩容
int TREEIFY_THRESHOLD = 8
这个值表示当某个桶中,链表长度大于 8 时,将链表转化成红黑树;如果哈希函数不合理,导致过多的数据碰撞,即使扩容也无法减少箱子中链表的长度,因此将链表转换成红黑树
int UNTREEIFY_THRESHOLD = 6:
当哈希表在扩容时,如果桶中的链表长度小于 6,则会由树重新退化为链表
int MIN_TREEIFY_CAPACITY = 64:
即哈希表中的桶数量要大于64才会考虑将链表转换成树,也是避免在小容量的时候进行不必要的转换
初始容量和负载因子
红黑树和链表转化
HashMap的内部数据结构
HashMap内部哈希算法
以上四节均学习于此文章:
源码解析-深刻理解Hash HashTable HashMap原理及数据hash碰撞问题
参考文章
官网描述
菜鸟教程
【深入Java基础】HashMap的基本用法