HashMap与ArrayList在找某个元素时的速度差异

前言

在软件构造课的实验5时,需要对大数据测试来判断我们程序的性能,最后我的时间总是比室友要慢几秒,在确定了我们读取文件的方式,构建轨道的算法基本复杂度没有区别时,就更加让我疑惑了,最后在仔细对比两个人的算法和rep的区别后,发现有个地方我使用的是Arraylist,而他使用的是hashmap,然后都有在这两个结构里进行查找的需求,本来我以为查找都应该是线性的,却忘记了hash的查找上的优势

原理

对于ArrayList,如果我们想要找到一个元素,但是我们并不知道这个元素在里面的位置,比如:

// An highlighted block
List<Friend> list = new Arraylist;

我们有一个String类型的ArrayList,这时如果我们要在里面找一个friend,我们只知道这个人的名字,那么这个时候我们只能通过遍历的方法

// An highlighted block
For(Friend friend:list){
if(friend.name.equals(name)){
....
}
}

这也是我当时的实现逻辑
然后我发现室友用了一种比较巧妙的方法,他定义了这样的一个map

// An highlighted block
Map<String,Friend> map = new HashMap<>();

这里的String就是这个人姓名,然后value里面还是我们刚才的Friend对象,这时如果我们想要找到某个名字的friend,只需要使用get方法就好了

// An highlighted block
map.get(name);

而这里的get方法为什么这么快呢,这就是hash的好处了,我们可以去看这个函数的源代码

// An highlighted block
public V get(Object key) {
        if (key == null)
            return getForNullKey();
        int hash = hash(key.hashCode());
        //先定位到数组元素,再遍历该元素处的链表
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                return e.value;
        }
        return null;
}

我们发现它首先获得的是这个key的hash值,然后在一个table里去遍历,找到符合条件的entry,这里的这个table是什么呢,看下面这张图就清楚了。
HashMap与ArrayList在找某个元素时的速度差异_第1张图片
hashmap实际上维护了这样的一个数组加链表的结构,每一个链表就是我们上面看到的那个table,对我们的每个需要entry,根据key的hash值传到相应的地方,这样在get时,我们只需去对于的那个table去找而不是遍历所有的entry,这样在大数据时效率的提高是很明显的。

最后

这里只是给出了一个特殊场景下的一个特殊情况,其实在上个结构里面使用map的空间上消耗会更大,是以空间换时间了。具体平时使用时也需要我们自己去分析应该使用什么样的数据结构最好。

参考链接.

你可能感兴趣的:(JAVA)