HashMap学习

hashmap

1、hashmap 与 hashtable 的区别

  1. 线程安全
  2. null值
  3. 执行效率

2、hashmap

hashmap是java中常用的集合类之一,

  1. 继承自AbstractMap类,实现了 Map、Cloneable、java.io.Serializable 接口。
  2. 使用哈希表来存储键值对(key-value),通过将键值映射成哈希码来进行高效的插入、删除操作。
  3. 具有很快的访问速度,最多允许一条记录的键为 null,不支持线程同步。
java 复制代码
java.lang.Object
	java.util.AbstractMap<K,V>
		java.util.HashMap<K,V>
Type Parameters:
	K - the type of keys maintained by this map
	V - the type of mapped values
All Implemented Interfaces:
	Serializable, Cloneable, Map<K,V>
Direct Known Subclasses:
	LinkedHashMap, PrinterStateReasons

public 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、创建

java 复制代码
import java.util.HashMap; // 引入 HashMap 类
HashMap<Integer, String> A = new HashMap<Integer, String>();

2、添加元素 put() 方法:

当调用put方法的时候,先通过hashCode() 获取key 的hashCode,然后找到bucket位置,将Entry对象 存储到bucket上面。

java 复制代码
public class Test {
	public static void main(Strings[] args) {
		// 创建 HashMap 对象 A
		HashMap<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对象。

java 复制代码
public class Test{
	public static void main(String[] args) {
		// 创建 HashMap 对象 A
		HashMap<Integer, String> A = new HashMap<Integer, String>();
		// 添加键值对
		A.put(1, "apple");
		A.put(2, "banana");
		// 访问
		System.out.println(A.get(1));
	}
}

4、删除元素 remove(key)方法:

java 复制代码
public class Test{
	public static void main(String[] args) {
		// 创建 HashMap 对象 A
		HashMap<Integer, String> A = new HashMap<Integer, String>();
		// 添加键值对
		A.put(1, "apple");
		A.put(2, "banana");
		// 删除
		A.remove(1);
	}
}

5、删除所有元素 clear()方法

6、计算 HashMap 中元素的数量 size() 方法

7、 遍历

  1. 可以使用 for-each 来迭代 HashMap 中的元素
  2. 只想获得 key ,使用 KeySet() 方法,然后通过 get(key) 获取对应的 value
  3. 指向获得value,有getValue() 方法.
java 复制代码
// 方法一:
      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);
    }

变量介绍

该类提供了四种构造方法:

(1)HashMap()

Constructs an empty HashMap with the default initial capacity (16) and the default load factor (0.75).

java 复制代码
public HashMap(){
	this.loadFactor = DEFAULT_LOAD_FACTOR; //all other fields defaulted
}

这是我们用的比较频繁的一个构造方法了,没有特殊的写法,所有变量均是默认值

(2) HashMap(int initialCapacity)

Constructs an empty HashMap with the specified initial capacity and the default load factor (0.75).

java 复制代码
public HashMap(int initialCapacity) {
	this(initialCapacity, DEFAULT_LOAD_FACTOR);
}

该构造方法传入一个指定容量,然后调用另外一个重载的构造方法

(3) HashMap(int initialCapacity, float loadFactor)

Constructs an empty HashMap with the specified initial capacity and load factor.

java 复制代码
public HashMap(int initialCapacity, float loadFactor) {
	if(initialCapacity < 0)
		throw new IllegalArgumentException("Illegal initial capacity: " +
                                               initialCapacity");
    if (initialCapacity > MAXIMUM_CAPACITY)
            initialCapacity = MAXIMUM_CAPACITY;
    if(loadFactor <= 0 || Float.isNaN(loadFactor))
    	throw new IllegalArgumentException("Illegal load factor: " +
                                               loadFactor);
    this.loadFactor = loadFactor;
    this.threshold = tableSizeFor(initialCapacity);
}

该构造方法指定一个容量值和一个负载因子;从方法内部逻辑可以看出容量值小于0将会抛出异常,大于最大容量值就重置为最大值;负载因子 如果小于等于0或者是个非法数字也将会抛出异常;最后一句代码的意思是计算HashMap下次扩容时的阈值,也就是说HashMap并不会等被填满时才会进行扩容,而是达到这个阈值时就开始提前扩容

(4) HashMap(Map<? extends K,? extends V> m)

Constructs a new HashMap with the same mappings as the specified Map.

java 复制代码
    public HashMap(Map<? extends K, ? extends V> m) {
        this.loadFactor = DEFAULT_LOAD_FACTOR;
        // 将m中的所有键值对添加到HashMap
        putMapEntries(m, false);
    }
java 复制代码
    final void putMapEntries(Map<? extends K, ? extends V> m, boolean evict) {
        int s = m.size();
        if (s > 0) {
            if (table == null) { // pre-size
            	//数组没有初始化 重新计算阈值
                float ft = ((float)s / loadFactor) + 1.0F;
                int t = ((ft < (float)MAXIMUM_CAPACITY) ?
                         (int)ft : MAXIMUM_CAPACITY);
                if (t > threshold)
                    threshold = tableSizeFor(t);
            }
            else if (s > threshold)
               //已经初始化 如果大小大于阈值 需要扩容
                resize();
            //将m中所有键值对添加到本HashMap中
            for (Map.Entry<? extends K, ? extends V> e : m.entrySet()) {
                K key = e.getKey();
                V value = e.getValue();
                putVal(hash(key), key, value, false, evict);
            }
        }
    }

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的基本用法

相关推荐
Swift社区1 小时前
在 Swift 中实现字符串分割问题:以字典中的单词构造句子
开发语言·ios·swift
没头脑的ht1 小时前
Swift内存访问冲突
开发语言·ios·swift
没头脑的ht1 小时前
Swift闭包的本质
开发语言·ios·swift
wjs20241 小时前
Swift 数组
开发语言
吾日三省吾码2 小时前
JVM 性能调优
java
stm 学习ing2 小时前
FPGA 第十讲 避免latch的产生
c语言·开发语言·单片机·嵌入式硬件·fpga开发·fpga
湫ccc3 小时前
《Python基础》之字符串格式化输出
开发语言·python
弗拉唐3 小时前
springBoot,mp,ssm整合案例
java·spring boot·mybatis
Red Red3 小时前
网安基础知识|IDS入侵检测系统|IPS入侵防御系统|堡垒机|VPN|EDR|CC防御|云安全-VDC/VPC|安全服务
网络·笔记·学习·安全·web安全