Android性能优化—数据结构优化

本文探讨了为何学习数据结构的重要性,并通过一个幽默的故事来比喻。在Android开发中,对比了HashMap和SparseArray在内存使用和性能上的差异。实验结果显示,SparseArray在内存占用和读取速度上优于HashMap,适合于特定场景。文章提醒开发者应根据应用需求选择合适的数据结构。
摘要由CSDN通过智能技术生成

为什么要学习数据结构?

有个人上少林寺拜师学艺。大师指点说武功重在内力,应该先炼内功,然后再练外功,然后大师让他拿一根管子对着半缸水吹气,说什么时候能把缸里的水吹到溢出来,就证明内功达到至高境界了。于是他就日复一日地刻苦练习,三年过去了,没有任何效果,但他想:既然师父那么说就一定有他的道理。
于是继续修炼。就这样过了十年,还是不行。终于,他失望了,决定不再修炼准备回家。到家碰到他爹,他爹就问他,说你拜师学艺学了十年学得怎么样啊? 他觉得很没面子,遂失落地低头叹了口气,等他抬头再看——他爹不见了……

什么是性能优化?

一款app除了要有令人惊叹的功能和令人发指的交互之外,在性能上也应该追求丝滑的要求,这样才能更好地提高用户体验。
在这里插入图片描述

线性数据结构

在这里插入图片描述

在这里插入图片描述

Hash表

结合了数组和链表的优点,增删改查都很快。
在这里插入图片描述
在这里插入图片描述

HashMap

在这里插入图片描述

SparseArray

在这里插入图片描述
1.key数组即存储int型的key,是按顺序排序的,因为插入数据的时候是根据二分查找寻找待插入数据的下标的。
2.插入数据时先根据二分查找寻找下标index,在index位置插入数据,然后移动index位置后面的元素

比如在下面的数据中插入key为54的数据
在这里插入图片描述
先二分查找找到54的index是在50和100之间,然后在index位置分别插入key和value
在这里插入图片描述

在这里插入图片描述

HashMap 与 SparseArray

在这里插入图片描述

HashMap 和 SparseArray性能对比

public class HashMapSparseArrayActivity extends AppCompatActivity {
    private String TAG = "HashMapSparseArrayActivity";

    private Button btnHashMap;
    private Button btnSparseArray;
    private Button btnTimeuse;

    private HashMap hashMap = new HashMap();
    private SparseArray sparseArray = new SparseArray();

    final int LENGTH = 100000;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_hashmapspasearray);

        btnHashMap = findViewById(R.id.hashmap);
        btnSparseArray = findViewById(R.id.spasearray);
        btnTimeuse = findViewById(R.id.timeuse);

        btnHashMap.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AsyncTask() {

                    @Override
                    protected Object doInBackground(Object[] objects) {
                        long starttime = System.currentTimeMillis();
                        for (int i = 0; i < LENGTH; i++) {
                            hashMap.put(i, new byte[10]);
                        }
                        long endtime = System.currentTimeMillis();
                        Log.i(TAG, "hashmap caused: " + (endtime - starttime) + "ms");
                        return null;
                    }
                }.execute();
            }
        });

        btnSparseArray.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                new AsyncTask() {

                    @Override
                    protected Object doInBackground(Object[] objects) {
                        long starttime = System.currentTimeMillis();
                        for (int i = 0; i < LENGTH; i++) {
                            sparseArray.put(i, new byte[10]);
                        }
                        long endtime = System.currentTimeMillis();
                        Log.i(TAG, "sparsearray caused: " + (endtime - starttime) + "ms");
                        return null;
                    }
                }.execute();
            }
        });

        btnTimeuse.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //时间性能
                timerUseHashMap();
                timerUseSparseArray();
            }
        });
    }


    public void timerUseHashMap() {
        long starttime = System.currentTimeMillis();
        for (int i = 0; i < LENGTH; i++) {
            hashMap.get(i);
        }
        long endtime = System.currentTimeMillis();
        Log.i(TAG, "hashmap caused: " + (endtime - starttime) + "ms");
    }

    public void timerUseSparseArray() {
        long starttime = System.currentTimeMillis();
        for (int i = 0; i < LENGTH; i++) {
            sparseArray.get(i);
        }
        long endtime = System.currentTimeMillis();
        Log.i(TAG, "sparsearray caused: " + (endtime - starttime) + "ms");
    }

}

内存

两个按钮操作,分别执行:添加100000(10万)个数字到HashMap和SparseArray中。然后查看内存使用情况。

初始内存:

在这里插入图片描述
内存:6.6 MB

点击HashMap按钮后:
在这里插入图片描述
内存:14.1 MB,即HashMap占用内存7.5MB

点击SparseArray按钮后:
在这里插入图片描述
内存:18.2 MB,即SparseArray占用内存4.1MB

可以看出SparseArray使用的内存远远小于HashMap.

时间

点击HashMap按钮和SparseArray按钮后,再点击测试时间按钮:

hashmap caused: 1663ms
sparsearray caused: 6ms

可以看到读取相同数量的数据时,SparseArray消耗的时间比HashMap少很多。

数据结构如何选择

1.链表对于删除和新增数据操作比较快,数组对于查找和修改数据操作比较快,所以删除和新增数据操作多的场景用LinkedList,查找和修改操作多的场景用ArrayList。
2.SparseArray的key只能是int类型的,所以如果key不是int类型的,那只能选择HashMap ,但Android中有一种应用场景,可以在key是String类型的情况下也用SparseArray,因为Android会在编译的时候把所有的资源编译为一个唯一的int型的资源id(包括String类型的资源),所以可以将String类型的key都写在strings.xml文件里,比如string1、string2、string3,然后将R.string.string1,R.string.string2,R.string.string3作为key存入SparseArray中。
3.本文主要讲解如何对ArrayList和LinkedList、HashMap和SparseArray进行选择,其他数据结构(比如栈,队列,堆,图,红黑树,字典树,B树等等)也都是根据具体的应用场景进行选择的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值