Collection源码之路(3)——HashMap 上篇

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/LosingCarryJie/article/details/81589688

首先纠正一个错误,HashMap不属于Collection,而是属于Map,之所以本篇文章叫Collection源码之路,是为了和之前的文章呼应。

之前的两篇文章介绍我的我们实际开发中用到最多的ArrayList或者结构简单的LinkedList,但是找工作面试问得最多的却是HashMap,我被问了不下6次吧,当我仔细阅读源码的时候才发现,这个数据结构真的是精髓中的精髓,一篇文章讲起来可能会非常长,于是分几篇介绍。

首先我们看下HashMap的结构图

这里写图片描述

上面是数组,数组中的元素是链表或者红黑树,okay 先把这个大致结构认识下,我们开始补补课外知识

位运算&

我们知道 &符号在位运算的时候表示的含义是

& 两个数一个为0就为0

比如 a=1,b=1, a&b=1; a=1,b=0, a&b=0
比如 a=11,b=11, a&b=11; a=11,b=10, a&b=10
我们计算机是二进制计数,十进制8等于二进制的1000,位运算多用于2的n次方的数上是因为2的n次方数对于与运算来说是极其便利的,接下来举例说明

若b等于2的n次方,a%b=a&(b-1)

我们就以b=8,a分别为1和9为例

a=1时
 b =  1000
 b-1= 0111
 a=   0001
 a&(b-1)=0001a=9时
 b =  1000
 b-1= 0111
 a=   1001
 a&(b-1)=0001

简单来说,因为2的n次方-1这个数1比较多,不会影响除数,所以 知识点1:当b=2的次方的时候,a&(b-1)这个公式一般被用来求余数,如果b不等于2的n次方,这个规律就不存在了,读者可以去验证

若b等于2的n次方,a&b 要么值为0要么值为b

我们就以b=8,a分别为1和9为例

a=1时
 b =  1000
 a=   0001
 a&b=0000=0a=9时
 b =  1000
 a=   1001
 a&b=1000=8

所以 知识点2:当b=2的n次方的时候,a&b只能为0或者b

既然知识点一说可以通过这种方式求余数,那么我代码里面如果遇到18%8这种情况是写成18%8好还是写成18&(8-1)这种方式好呢?位运算效率更高

如果机器比较快是看不出来很大差距的,但是如果我们在android设备上测试就很容易看出来区别

 Log.i("TAG", "start: "+System.currentTimeMillis()%10000);
        for(int i=0;i<100000000;i++){
            if((i%1024)==0){

            }

        }
 Log.i("TAG", "end: "+System.currentTimeMillis()%10000);

平均消耗时间500ms左右

 Log.i("TAG", "start: "+System.currentTimeMillis()%10000);
        for(int i=0;i<100000000;i++){
            if((i&(1023))==0){

            }

        }
 Log.i("TAG", "end: "+System.currentTimeMillis()%10000);

平均消耗时间大约300ms

的确是位运算效率更高,为什么呢?在计算机处理中,加减很简单但是乘除很复杂,所以老一辈开发者在机器运行速度不快的时候更多考虑的是效率优先。

猜你喜欢

转载自blog.csdn.net/LosingCarryJie/article/details/81589688
今日推荐