前言
面试过程中经常会被问到HashMap或者ArrayList相关的问题,简单的话就会问一些使用方面上的区别,难一点的话就会问他们之间的关系和自身的原理,今天我们就由浅入深的来分析他们之间的原理与区别。
相同点
一、都是集合类:
1、首先HashMap和ArrayList都是类,也就是都是由class修饰的类而不是方法或者属性,这是其一。
2、其次HashMap和ArrayList都是集合,java中常见的集合有list、map、set等,所以这两个都是集合而不是数组或其它,这是其二。
不同点
一、数据结构不同。
HashMap
1、首先我们从源码来分析HashMap的常用的一些方法的底层是怎么实现的。首先来写一个main方法,方法中实例化一个HashMap。
public class JDK18 { public static void main(String[] args) { Map<String,String> map = new HashMap<String,String>(); map.put("1", "2"); } }
在这里可能有小伙伴问为什么前面用 Map<String,String> map后面用 new HashMap<String,String>();为什么不直接写一个Map<String,String> map = new Map<String,String>();呢,为什么非要用HashMap呢,因为Map是一种集合类型,他是以一个key,value键值对方式进行存储的,但是这钟键以什么样的算法来生成数据存储到我们的空间中是不同的,所以由于算法的不同,map也有不同的实现方式,比如HashMap、TreeMap、ConrrentHashMap等,而且Map只是一个接口,里面只有接口方法而没有实现,而这些HashMap继承并实现了Map的接口,所以我们需要new一个具体的Map类才可以使用。下面我们按住ctrl点击put进入。
我们可以看到源码,如果你点击不能够看到源码证明你还没有配置,你可以根据网上的教程配置一下源码就可以看源码了。这里我们可以看到我们进入的是Map.class类当中,前面我们说过Map类只是一个接口类,里面只定义了接口并没有实现,所以我们复制一下put方法去HashMap.class类中搜索这个方法。
这里我们找到了这个方法,但是他还return了一个putVal方法,我们一会要点进putVal这个方法来查看具体的算法,这个时候我们看到putVal方法的第一个参数是将我们输入的key值做了一个hash()操作,这个时候我们点击这个hash方法里面查看一下。
点进去我们可以看到如下的一个三元运算
这里如果传入的key是null,就返回0,这个先不关注,先看有key值的时候是怎么计算的,有key值的话首先对key进行一个key.hashCode()方法的调用,我们点击去这个方法可以看到
他是一个用native修饰的方法,在这里说一下用native修饰的方法是底层用c语言封装的一个方法,我们在这里无法看到,但是我们可以用String new一个字符串然后调用hashCode()方法输出一下,比如String str = ‘a’;,那么他的hashCode()方法输出来的是97,这里是不是跟ASSIC很像,这个hashCode()是一个怎样的算法我们后期再讨论,这里我们先明白首先把我们的key值调用了一个hashCode()方法的运算,然后再^上一个h的无符号右移16位。
这里的无符号右移我们java基础中都学过例如h的二进制为下面这样
00000000 10101010 01010101 10101010
当我们无符号右移16位后就变成了这样
00000000 00000000 00000000 10101010
我们从左往右移动了16位,空出来的位置都用0来填充,最后将右移后的二进制与h的二进制来进行^操作,这样就是得到的key值,为什么要进行一个这样的异或操作呢,是为了让结果更加散列,这样的话可以减少Hash碰撞的几率。
ArrayList
我们接下来看一下ArrayList的源码,我们首先写一个简单的实例
List<String> list = new ArrayList<String>(); list.add("1");
我们可以看到我们传入的参数是一个参数,而不是HashMap的key,value形式的两个参数,这是其中一点不同,而ArrayList插入的顺序是默认++排队插入的,图
这里将传入的参数e插入到数组elementData【size++】的位置,而HashMap插入的位置是根据key算出的hashCode来决定插入的位置的,所以ArrayList是有序的,而HashMap是无序的。
总结
HashMap和ArrayList都是集合类,但是他们的存储结构有所不同,存储的方式也有所不同,假如我们有一个表单页面要显示所有的订单,我们可以使用ArrayList存储然后循环显示在页面上。假如我们要存储一个人的基本信息,可以用HashMap存储 key=“name”,value=“张三”,key=“password”,value=”123456“,这种的参数,所以我们在开发过程中根据实际情况来决定使用哪一种。