JDK1.7和1.8的HashMap对比详解

HashMap是我们在编程中最常用的map,也是面试中经常考的问题,所以打算深入研究一下hashmap的源码,并且对比7和8中的不同。
一、hashmap的数据结构
hashmap的数据结构是哈希表,核心是基于哈希值的桶,而哈希桶的底层实现其实是数组,数组这种数据结构查找的时间复杂度是O(1),所以哈希表的查找、删除、插入的平均时间复杂度就是O(1),但是它也有一个致命的缺陷—哈希碰撞(collision),所谓碰撞,举例说明:两个数据映射出来的哈希值相同,就会发生哈希碰撞(冲突)。下面我们来看下java7和java8分别是怎么解决碰撞问题的。
二、Java 7 HashMap(不是线程安全的)
经典的哈希表的实现—数组+链表,即如果put到的位置有值了,如果key不一致,则会将新put进来的数据放到这个位置原有值的后面,形成链表。画了个图简单展示下:
在这里插入图片描述
先来看几个重要的常量,简单的介绍我已经写在了下面的注释中了,其实就是把他给的英文注释简单翻译一下,他给的英文注释很清晰明了了

/**
 * The default initial capacity - MUST be a power of two.
 * 默认的初始化容量,必须是2的幂次方,默认容量是16(2^4)
 * 疑问一:为什么必须是2的幂次方,这样赋值的目的是什么?
 */
static final int DEFAULT_INITIAL_CAPACITY = 1 << 4; // aka 16

/**
 * The maximum capacity, used if a higher value is implicitly specified
 * by either of the constructors with arguments.
 * MUST be a power of two <= 1<<30.
 * 最大容量,这个值我们一般用不上
 */
static final int MAXIMUM_CAPACITY = 1 << 30;

/**
 * The load factor used when none specified in constructor.
 * 加载因子,默认0.75,加载因子用来判断什么时候需要对hashmap进行resize()
 */
 static final float DEFAULT_LOAD_FACTOR = 0.75f;

这里有个疑问,就是为什么初始化容量一定是2^n,这个我们先留着,稍后进行解答。
下面我们先去看下他的默认构造函数HashMap()

	/**
     * Constructs an empty <tt>HashMap</tt> with the default initial capacity
     * (16) and the default load factor (0.75).
     * 默认的构造函数,初始容量为16,加载因子为0.75
     */
    public HashMap() {
        this.loadFactor = DEFAULT_LOAD_FACTOR; // all other fields defaulted
    }

当然,还有可调初始容量和加载因子的构造函数

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);
    }
	/**
     * Inflates the table
     */
    private vois inflateTable(int toSize) {
        iint capacity=roundUpToPowerOf2(toSize);
        ...//实际开辟空间存储元素
	}

这里有一个需要注意的地方,当你输入的initialCapacity不是2^n,roundUpToPowerOf2(param)方法会自动将你输入的值调整为离他最大的 2的幂次方。这里说一句,并不是调用了构造函数的时候就会开辟空间,而是等到调用put方法时才会真正开辟空间存储元素(默认16)。

如何确定这个obj应该对应哪个哈希桶的索引呢?
hashcode

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值