HashMap和ArrayMap的区别

来源:互联网 发布:txt数据导入origin 编辑:程序博客网 时间:2024/06/01 10:05

那HashMap和ArrayMap到底不同在哪呢,主要有以下几个方面:

1、存储方式不同

HashMap内部有一个HashMapEntry

[java] view plaincopy   @Override public V put(K key, V value) {        if (key == null) {            return putValueForNullKey(value);        }        int hash = secondaryHash(key);        HashMapEntry<K, V>[] tab = table;        int index = hash & (tab.length - 1);     //先查找有没有对应的key值,如果有,就改写value,并返回改写前的value值:oldValue        for (HashMapEntry<K, V> e = tab[index]; e != null; e = e.next) {            if (e.hash == hash && key.equals(e.key)) {                preModify(e);                V oldValue = e.value;                e.value = value;                return oldValue;            }        }        // No entry for (non-null) key is present; create one        modCount++;        if (size++ > threshold) {         //扩容,双倍            tab = doubleCapacity();            index = hash & (tab.length - 1);        }        addNewEntry(key, value, hash, index);        return null;    } //创建对象存储键值对    void addNewEntry(K key, V value, int hash, int index) {        table[index] = new HashMapEntry<K, V>(key, value, hash, table[index]);    } 
    ArrayMap的存储中没有Entry这个东西,他是由两个数组来维护的
[java] view plaincopyint[] mHashes; Object[] mArray; 

mHashes数组中保存的是每一项的HashCode值,mArray中就是键值对,每两个元素代表一个键值对,前面保存key,后面的保存value,我们看看下面代码的结果:

[java] view plaincopyarraymap = new HashMap<String, String>(); a.put("a", "a_value"); a.put("b", "b_value"); 

是不是能清楚地看到ArrayMap的存储了,这种存储在put代码中如下:

[java] view plaincopymHashes[index] = hash; mArray[index<<1] = key; mArray[(index<<1)+1] = value; 

2、添加数据时扩容时的处理不一样

先来看看HashMap

[java] view plaincopyif (size++ > threshold) {     tab = doubleCapacity();     index = hash & (tab.length - 1); } doubleCapacity进行双倍扩容,它的代码中有这么一句话[java] view plaincopyHashMapEntry<K, V>[] newTable = makeTable(newCapacity); 

最终,这个newTable将作为扩容后的新对象返回,那么makeTable做了什么呢,如下:

[java] view plaincopyprivate HashMapEntry<K, V>[] makeTable(int newCapacity) {     @SuppressWarnings("unchecked") HashMapEntry<K, V>[] newTable             = (HashMapEntry<K, V>[]) new HashMapEntry[newCapacity];     table = newTable;     threshold = (newCapacity >> 1) + (newCapacity >> 2); // 3/4 capacity     return newTable; } 

我们清楚地看到,这里进行了new操作,重新创建对象,开销很大。
那么ArrayMap呢,看看:

[java] view plaincopy//如果容量不够 ize >= mHashes.length) {     final int n = mSize >= (BASE_SIZE*2) ? (mSize+(mSize>>1))             : (mSize >= BASE_SIZE ? (BASE_SIZE*2) : BASE_SIZE);     if (DEBUG) Log.d(TAG, "put: grow from " + mHashes.length + " to " + n);     final int[] ohashes = mHashes;     final Object[] oarray = mArray; //分配数组     allocArrays(n);     if (mHashes.length > 0) {         if (DEBUG) Log.d(TAG, "put: copy 0-" + mSize + " to 0");         //特别注意这,是copy,而不是new,效率提升         System.arraycopy(ohashes, 0, mHashes, 0, ohashes.length);         System.arraycopy(oarray, 0, mArray, 0, oarray.length);     }         //释放无用空间,收缩数组     freeArrays(ohashes, oarray, mSize); } 

ArrayMap用的是copy数据,所以效率相对要高。

3、ArrayMap提供了数组收缩的功能,在clear或remove后,会重新收缩数组,是否空间

4、ArrayMap采用二分法查找;

以上就是android开发中,HashMap与ArrayMap的区别,大家在涉及到内存方面的实现,可根据实际情况选择这两种不同的方式。