一次面试被问到ArrayMap,原理及源码分析详解

本文详细分析了Android SDK中的ArrayMap数据结构,对比HashMap,解释了ArrayMap在小数据量时提高内存效率的优势。通过源码解读,阐述了ArrayMap的存储方式、插入、查找和删除操作的实现,包括如何处理哈希冲突,以及在特定情况下进行数据压缩以节省内存。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、前言

在 《SparseArray详解及源码简析》中,我们熟悉了 SparseArray 的基本用法、特点以及实现原理。而在 Android SDK 的这个工具包中还有一个同样重要的数据结构 ArrayMap,其目的也是在当数据量较小,比如几百个的时候,可以用来替代 HashMap,以提高内存的使用效率。

如果对 HashMap 的实现感兴趣的话,可以看看《HashMap详解以及源码分析》,而这篇文章就来了解一下 ArrayMap 的使用及其实现原理。

二、 源码简析

1. demo 及其简析

分析代码之前同样先看一段 demo,后面同样通过 demo 进行实现原理的分析。

        ArrayMap<String,String> arrayMap = new ArrayMap<>();
        arrayMap.put(null,"张大哥");
        arrayMap.put("abcd","A大哥");
        arrayMap.put("aabb","巴大哥");
        arrayMap.put("aacc","牛大哥");
        arrayMap.put("aadd","牛大哥");
        arrayMap.put("abcd","B大哥");

        Set<ArrayMap.Entry<String,String>> sets = arrayMap.entrySet();
        for (ArrayMap.Entry<String,String> set : sets) {
            Log.d(TAG, "arrayMapSample: key = " + set.getKey() + ";value = " + set.getValue());
        }

代码中,实际插入了 6 个 Key-Value,然而输出只有 5 个,其中 Key 为 “abcd” 的重复了而发生了覆盖。另外,还有一点注意的是 null 为 key 是允许插入的。以下是其输出的结果。

arrayMapSample: key = null;value = 张大哥 arrayMapSample: key = aabb;value = 巴大哥 arrayMapSample: key = aacc;value = 牛大哥 arrayMapSample: key = aadd;value = 牛大哥 arrayMapSample: key = abcd;value = B大哥

通过 Android Studio 的 Debug 功能,也可以简单观察一下其在内存中的存储。

2.源码分析

先来简单看一下 ArrayMap 的类图结构。

与 HashMap 不同的是,它是直接实现自接口 map。同样,存储 key-value 的方式也不同。ArrayMap 是通过数组直接存储了所有的 key-value。其中,mHashes 在 index 处存储了 key 的 hash code,而 mArray 则在 hash code 的 index<<1 处存储 key,在 index<<1 + 1 处存储 value。简单点说就是偶数处存储 key,相邻奇数处存储 value。

  • ArrayMap 的初始化
     /**
     * Create a new empty ArrayMap.  The default capacity of an array map is 0, and
     * will grow once items are added to it.
     */
    public ArrayMap() {
        this(0, false);
    }

    /**
     * Create a new ArrayMap with a given initial capacity.
     */
    public ArrayMap(int capacity) {
        this(capacity, false);
    }

    /** {@hide} */
    public ArrayMap(int capacity, boolean identityHashCode) {
        mIdentityHashCode = identityHashCode;

        // If this is immutable, use the sentinal EMPTY_IMMUTABLE_INTS
        // instance instead of the usual EmptyArray.INT. The reference
        // is checked later to see if the array is allowed to grow.
        if (capacity < 0) {
            mHashes = EMPTY_IMMUTABLE_INTS;
            mArray = EmptyArray.OBJECT;
        } else if (capacity == 0) {
            mHashes = EmptyArray.INT;
            mArray = EmptyArray.OBJECT;
        } else {
            allocArrays(capacity);
        
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值