“为什么HashMap比Hashset快” 凭什么这么说?


标题解释

这是一个很有争议性的描述,看过HashSet源码的同学肯定知道,这几乎就是HashMap来做的,只是把元素存放在Key上,而完全没有用到map的Value,其他的所有操作都是几乎简单的调用了HashMap的,那么他们的性能本身应该就没什么可比较的了——理应没区别。

可是直到看到了这样一张表:
某被复制来复制去的图片


思考

这里说到——“HashMap比较快,是因为使用了唯一的键来获取对象”

也就是说,图的观点在于我们取对象时,HashMap可以直接通过hash计算得到的键来获取对象,而HashSet呢, 直接用HashMap的containKeys方法,确实能在相同效率下确定一个元素是否存在,但是因为实现的是set,并不需要get方法,因此取值很麻烦。

那我们来看看他们的取值:

  • HashMap取值(随便看看get的源码)
public V get(Object key) {
        Node<K,V> e;
        return (e = getNode(hash(key), key)) == null ? null : e.value;
    }

    /**
     * Implements Map.get and related methods.
     *
     * @param hash hash for key
     * @param key the key
     * @return the node, or null if none
     */
    final Node<K,V> getNode(int hash, Object key) {
        Node<K,V>[] tab; Node<K,V> first, e; int n; K k;
        if ((tab = table) != null && (n = tab.length) > 0 &&
            (first = tab[(n - 1) & hash]) != null) {
            if (first.hash == hash && // always check first node
                ((k = first.key) == key || (key != null && key.equals(k))))
                return first;
            if ((e = first.next) != null) {
                if (first instanceof TreeNode)
                    return ((TreeNode<K,V>)first).getTreeNode(hash, key);
                do {
                    if (e.hash == hash &&
                        ((k = e.key) == key || (key != null && key.equals(k))))
                        return e;
                } while ((e = e.next) != null);
            }
        }
        return null;
    }
  • 那HashSet呢?

    只有迭代器了。

Iterator it = set.iterator();
		 while(it.hasNext()){
			 System.out.print(it.next() + " ");
		}

那么最后图片想说的就是这?从无序的set中取值要遍历所以慢?

真的是这个结构性问题吗?那这也太牵强了


说法源头

最终找到了这个说法的源头,是国外的某个技术博客的描述:

https://stackoverflow.com/questions/16278995/why-is-hashmap-faster-than-hashset

提问说:

I am not quite understanding the following statements:
HashMap is faster than HashSet because the values are associated to a unique key.

终于得到了比较靠谱的答案:

None of these answers really explain why HashMap is faster than HashSet. They both have to calculate the hashcode, but think about the nature of the key of a HashMap - it is typically a simple String or even a number. Calculating the hashcode of that is much faster than the default hashcode calculation of an entire object. If the key of the HashMap was the same object as that stored in a HashSet, there would be no real difference in performance. The difference comes in the what sort of object is the HashMap’s key.

翻译一下:

他们俩都必须计算哈希码,但要考虑HashMap的键的性质-它通常是一个简单的String甚至是一个数字。

而 String和Integer的计算哈希码的速度 比 整个对象的默认哈希码 计算要快得多

换句话说

  • 如果HashMap的键与存储在HashSet中的键是相同的对象,则性能将没有真正的区别。区别在于HashMap的键是哪种对象。

至此,可以得出结论:

  • 他们的性能差距最终还是体现在了K-V结构的乱用上。

    HashMap说,我的K-V可不是把K随便扔给你用的

    省事儿一时爽,K值不好还得搞

PS:初写文,希望各位大佬多指点

  • 22
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 10
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值