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

news2024/9/24 3:27:22

优化数据结构是提高Android应用性能的重要一环。在Android开发中,ArrayList、LinkedList和HashMap等常用的数据结构的正确使用对APP性能的提升有着重大的影响。

一、ArrayList

ArrayList内部使用的是数组,默认大小10,当数组长度不足时,会进行扩容,扩容后的长度为原来的1.5倍。扩容实际上是新建一个长度为原数组1.5的新数组,然后遍历原数组,将数据一一赋值给新数组。

add(position,object) 给指定位置添加元素时,会将该元素及其下标后面的元素都往后移动一位,
最后将add的元素添加到position位置。

delete(position) 删除指定位置元素,删除该元素,并将该元素下标后面的元素都往前移动一位。

由于添加和删除指定位置的元素,其后面的元素需要移动,造成耗时,速度慢,在尾部添加和删除不需要移动,不受影响。

优缺点:

读取速度快,尾部添加和删除速度快,中途添加和删除速度慢。

使用场景:

1)ArrayList提供了常数时间复杂度的随机访问操作(get和set方法),因为它内部使用数组来存储元素,可以通过索引直接访问元素。

2)ArrayList对于在末尾添加或删除元素的操作具有较好的性能,时间复杂度为O(1)。当需要在集合的尾部频繁添加和删除元素时,可以使用ArrayList。

3)ArrayList对于在中间位置插入或删除元素的操作性能较差,因为需要移动后续元素来保持顺序。如果需要频繁在集合的中间位置进行插入或删除操作,LinkedList更适合。

4)在创建ArrayList时,如果能够预估元素数量,可以通过指定初始容量,避免频繁的扩容操作,提高性能。

数组特点:

存储区间是连续,且占用内存严重,空间复杂也很大,时间复杂为O(1)。

优点:是随机读取效率很高,原因数组是连续(随机访问性强,查找速度快)。

缺点:插入和删除数据效率低,因插入数据,这个位置后面的数据在内存中要往后移的,且大小固定不易动态扩展。

二、LinkList

双链表结构,添加和删除速度快;查询需要从头遍历所有节点,速度慢。不需要连续内存,不会导致内存浪费。

链表特点:

区间离散,占用内存宽松,空间复杂度小,时间复杂度O(N)。

优点:插入删除速度快,内存利用率高,没有大小固定,扩展灵活。

缺点:不能随机查找,每次都是从第一个开始遍历(查询效率低)。

使用场景:

1)需要频繁在集合的中间位置插入或删除元素;

2)不需要频繁随机访问元素;

3)需要高效的插入和删除操作而不关心空间开销,LinkedList在插入和删除操作上的性能优于ArrayList,但它需要额外的空间来存储链表节点的指针,因此在空间开销上相对较高。

三、HashMap

1.7及之前使用 数组+链表

1.7之后使用 数组+链表+红黑树

 

数组+链表:

HashMap数组默认长度16,加载因子默认0.75f,当数组中存储的元素 > 0.75*数组长度 时,需要扩容,将数组长度扩容为原来的2倍,以保证为2的整数次幂。

HashMap以key-value成对出现,一个key对应一个value;

put:key-value
通过key获取hash值,然后跟数组长度取模 == key-value存储在数组的下标;
然后将key、hash值、value、下一个节点,封装成一个节点,插到链表的头节点 -- 头插法

get:key
通过key获取hash值,然后跟数组长度取模 == key-value存储在数组的下标;
然后遍历数组下标元素--链表,通过判断节点的key值一致,返回对应的节点。

  

扩容:

由于扩容后数组长度不一致,导致按原数组长度计算的下标失效,所以在扩容后,需要将原HashMap保存元素遍历,按新的数组长度,重新计算数组下标,存储。该过程耗时,故尽量在使用HashMap时,评估实际数组的长度,在创建HashMap时指定其长度,避免出现扩容的情况。

优缺点:

数组的特点:查询效率高,插入,删除效率低。

链表的特点:查询效率低,插入删除效率高。

在HashMap底层使用数组+链表+红黑树的结构完美的解决了数组和链表的问题,使得查询和插入,删除的效率都很高。

当数组中存储的元素 > 0.75*数组长度时,需要扩容,导致HashMap至少有25%的空间浪费,无疑是使用了空间换时间的方式去提高效率。

四、SparseArray

Android为了解决HashMap存在的空间浪费问题,推出的新数据类型;采用双数组的方式+HashMap的思想+二分查找,解决HashMap浪费空间的同时,提高了效率。

  

缺点:SparseArray的key只能是int类型

SparseArray采用了延迟删除的机制,通过将删除KEY的Value设置DELETED,方便之后对该下标的存储进行复用;

使用二分查找,时间复杂度为O(LogN),如果没有查找到,那么取反返回左边界,再取反后,左边界即为应该插入的数组下标;

如果无法直接插入,则根据mGarbage标识(是否有潜在延迟删除的无效数据),进行数据清除,再通过System.arraycopy进行数组后移,将目标元素插入二分查找左边界对应的下标;

mSize小于等于keys.length,小于的部分为空数据或者是gc后前移的数据的原数据(也是无效数据),因此二分查找的右边界以mSize为准;

mSize包含了延迟删除后的元素个数;如果遇到频繁删除,不会触发gc机制,导致mSize 远大于有效数组长度,造成性能损耗;

mGarbage为true不一定有无效元素,因为可能被删除的元素恰好被新添加的元素覆盖;

  

使用场景:

key为整型;不需要频繁的删除;元素个数相对较少。

五、ArrayMap

实现了Map接口,并使用int[]数来存储key的hash值,数组的索引用作index,而使用Object[]数组来存储key<->value ,这还是比较新颖的 。

使用二分查找查找hash值在key数组中的位置,然后根据这个位置得到value数组中对应位置的元素。

和SparseArray类似,当数据有几百条时,性能会比HashMap低50%,因此ArrayMap适用于数据量很小的场景

ArrayMap和HashMap的区别:

1)ArrayMap的存在是为了解决HashMap占用内存大的问题,它内部使用了一个int数组用来存储元素的hashcode,使用了一个Object数组用来存储元素,两者根据索引对应形成key-value结构,这样就不用像HashMap那样需要额外的创建Entry对象来存储,减少了内存占用。但是在数据量比较大时,ArrayMap的性能就会远低于HashMap,因为 ArrayMap基于二分查找算法来查找元素的,并且数组的插入操作如果不是末尾的话需要挪动数组元素,效率较低。

2)而HashMap内部基于数组+单向链表+红黑树实现,也是key-value结构, 正如刚才提到的,HashMap每put一个元素都需要创建一个Entry来存放元素,导致它的内存占用会比较大,但是在大数据量的时候,因为HashMap中当出现冲突时,冲突的数据量大于8,就会从单向链表转换成红黑树,而红黑树的插入、删除、查找的时间复杂度为O(logn),相对于ArrayMap的数组而言在插入和删除操作上要快不少,所以数据量上百的情况下,使用HashMap会有更高的效率。

如何解决冲突问题:

在ArrayMap中,假设存在冲突的话,并不会像HashMap那样使用单向链表或红黑树来保留这些冲突的元素,而是全部key、value都存储到一个数组当中,然后查找的话通过二分查找进行,这也就是当数据量大时不宜用ArrayMap的原因了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/839404.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

探索OLED透明屏的参数及其在不同领域的应用

OLED透明屏作为一种创新的显示技术&#xff0c;具有高透明度、色彩鲜艳、观感独特等特点&#xff0c;正逐渐成为各个领域的热门选择。 为帮助您更好地了解和选择适合自己需求的OLED透明屏&#xff0c;尼伽便给您详细介绍一下OLED透明屏的参数&#xff0c;包括屏幕尺寸、分辨率…

SQL注入上传文件获取shell

SQL注入写文件的三个必要条件 Web目录有读写权限&#xff1a; 当目标网站的Web目录具有读写权限时&#xff0c;攻击者可以通过注入恶意SQL语句将恶意文件写入服务器上的Web目录。 知道文件的绝对路径&#xff1a; 攻击者需要知道目标系统上的文件的绝对路径&#xff0c;以便将…

Uni-Dock:GPU 分子对接使用教程

github文件下载&#xff1a; git clone https://github.com/dptech-corp/Uni-Dock.git cd Uni-Dock/example/screening_test wget https://github.com/dptech-corp/Uni-Dock/releases/download/1.0.0/unidock 将此文件加入到全局变量中 chmod x unidock sudo mv unidock /…

杂记 | 记录一次使用Docker安装gitlab-ce的过程(含配置交换内存)

文章目录 01 准备工作02 &#xff08;可选&#xff09;配置交换内存03 编辑docker-compose.yml04 启动并修改配置05 nginx反向代理06 &#xff08;可选&#xff09;修改配置文件07 访问并登录 01 准备工作 最近想自建一个gitlab服务来保存自己的项目&#xff0c;于是找到gitla…

Flink CEP(三)pattern动态更新

线上运行的CEP中肯定经常遇到规则变更的情况&#xff0c;如果每次变更时都将任务重启、重新发布是非常不优雅的。尤其在营销或者风控这种对实时性要求比较高的场景&#xff0c;如果规则窗口过长&#xff08;一两个星期&#xff09;&#xff0c;状态过大&#xff0c;就会导致重启…

策略模式(C++)

定义 定义一系列算法&#xff0c;把它们一个个封装起来&#xff0c;并且使它们可互相替换((变化)。该模式使得算法可独立手使用它的客户程序稳定)而变化(扩展&#xff0c;子类化)。 ——《设计模式》GoF 使用场景 在软件构建过程中&#xff0c;某些对象使用的算法可能多种多…

24考研数据结构-并查集

目录 5.5.2 并查集&#xff08;双亲表示法&#xff09;1. 并查集的存储结构2. 并查集的代码实现初始化并查时间复杂度union操作的优化&#xff08;不要瘦高的树&#xff09;并查集的进一步优化&#xff08;find的优化&#xff0c;压缩路径&#xff09;优化总结 数据结构&#x…

大模型使用——超算上部署LLAMA-2-70B-Chat

大模型使用——超算上部署LLAMA-2-70B-Chat 前言 1、本机为Inspiron 5005&#xff0c;为64位&#xff0c;所用操作系统为Windos 10。超算的操作系统为基于Centos的linux&#xff0c;GPU配置为A100&#xff0c;所使用开发环境为Anaconda。 2、本教程主要实现了在超算上部署LLAM…

SpringBoot整合redis集群实现读写分离(哨兵模式)

1 首先要在Linux虚拟机上安装redis # 安装包存放目录 cd /usr/local/redis # 下载最新稳定版 wget https://download.redis.io/releases/redis-6.2.6.tar.gz # 解压 tar -zxvf redis-6.2.6.tar.gz # 进入解压后的目录 cd /usr/local/redis/redis-6.2.6/ # 编译 make # 执行 &q…

系列二、IOC基本概念和底层原理

一、IOC基本概念 控制反转&#xff1a;把对象创建和对象之间的调用过程&#xff0c;交给Spring进行管理&#xff1b;使用IOC的目的&#xff1a;减低耦合度&#xff1b; 二、IOC底层原理 xml解析 工厂模式 反射 2.1、图解IOC底层原理 # 第一步&#xff1a;xml配置文件&am…

【小沐学NLP】在线AI绘画网站(网易云课堂:AI绘画工坊)

文章目录 1、简介1.1 参与方式1.2 模型简介 2、使用费用3、操作步骤3.1 选择模型3.2 输入提示词3.3 调整参数3.4 图片生成 4、测试例子4.1 小狗4.2 蜘蛛侠4.3 人物4.4 龙猫 结语 1、简介 Stable Diffusion是一种强大的图像生成AI&#xff0c;它可以根据输入的文字描述词&#…

AI驱动的靶点发现综述

疾病建模和靶点识别是药物发现中最关键的初始步骤。传统的靶点识别是一个耗时的过程&#xff0c;需要数年至数十年的时间&#xff0c;并且通常从学术报告开始。鉴于其分析大型数据集和复杂生物网络的优势&#xff0c;人工智能在现代药物靶点识别中发挥着越来越重要的作用。该综…

telnet检验网络能不能通

telnet检测网络能不能通&#xff08;ip地址端口号&#xff09;

wait,notify/notifyAll都要放在synchronized锁里面

wait&#xff0c;notify/notifyAll都要放在synchronized锁里面 如果没放在synchronized锁里面&#xff0c;就要报这样的错误 public class Test5 {public static void main(String[] args) throws InterruptedException {Thread t1 new Thread(()->{syn();},"t1&quo…

【C高级】Day 3 shell

1. 整理思维导图 3. 输入一个文件名&#xff0c;判断是否为shell脚本文件&#xff0c;如果是脚本文件&#xff0c;判断是否有可执行权限&#xff0c;如果有可执行权限&#xff0c;运行文件&#xff0c;如果没有可执行权限&#xff0c;给文件添加可执行权限。 #!/bin/bash rea…

python制作小程序制作流程,用python编写一个小程序

这篇文章主要介绍了python制作小程序代码宠物运输&#xff0c;具有一定借鉴价值&#xff0c;需要的朋友可以参考下。希望大家阅读完这篇文章后大有收获&#xff0c;下面让小编带着大家一起了解一下。 1 importtkinter2 importtkinter.messagebox3 importmath4 classJSQ:5 6 7 d…

CAM,PradCAM,layer CAM(可解释性分析方法)

目录 1.CAM 1.1作用 1.2应用实例 1.3CAM的特点 1.4CAM的思路 1.5CAM的缺点 2.GradCAM 2.1和GAM的区别及思路 2.2应用面 2.3一个延深&#xff08;解决模型偏见&#xff09; 2.4缺点 3.Grad CAM 4.Score CAM 5.layer CAM 参考文献 1.CAM 1.1作用 CAM不不光可以分类还…

前端JS实用操作符,一些骚操作✨

目录 0、!! 双重逻辑非操作符 &#x1f4da; 1、?? 操作符 空值合并/空判断 ✅ 2、?. 可选链运算符&#x1f50d; 3、?? 操作符 逻辑空值赋值运算符 &#x1f49a; 4、三元运算符 &#x1f4d7; 5、~~ 操作符 双位运算符 &#x1f528; 6、&&与 ||或 短…

在java中操作redis_Data

1.引入依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 2.配置Redis数据源 redis:host: ${sky.redis.host}port: ${sky.redis.port}password: ${sk…

揭秘程序员最喜欢的5个高薪工作

大家好&#xff0c;这里是程序员晚枫。想了解更多精彩内容&#xff0c;快来关注程序员晚枫 今天给大家推荐5个适合程序员的高薪岗位。 01 推荐岗位 以下是5个工资最高的程序员工作&#xff1a; 数据科学家&#xff1a;数据科学家是负责数据收集、处理、分析和报告的专业人员。…