Android Note - 代码优化

这篇主要讲一些平时写代码时优化的小技巧。虽然看上去都是一些很小的细节,但是积少成多,量变到一定程度也会发生质变,积累的性能提升效果还是不可忽视的。平时碰到这些问题时一定要多留心,提升自己编码水平的同时也能加强代码的健壮性。


正确选择数据类型

这里简单介绍一些常用的数据类型的选择与使用场景。

String & StringBuilder

我们平时在Java中做字符串连接的时候,下意识的选择都是使用 + 来连接。这个过程其实会新生成一个 StringBuilder 对象,然后将 + 左右的数据通过 append() 方法拼接起来,本质上就是使用StringBuilder对象进行字符串连接。所以在拼接频繁的场景(比如循环)中,如果使用 + 就相当于每次都会新建一个StringBuilder对象。而我们知道,频繁新建对象是很消耗性能的,而且在循环中也容易发生内存抖动。

结论:在单条语句中使用 + 直接拼接没有效率问题;拼接频繁的场景请使用 StringBuilder

另外,还有个StringBuffer 用法与 StringBuilder几乎一样,只是前者是线程安全的而后者非线程安全,这里就不展开说了。

基本数据类型的选择

其实原理很简单,不同的数据类型,占用的内存空间不一样。比如int只占了 4 个字节,而long占用了 8 个字节,很明显地处理起来 int 要快于 long。但是,在具体的工作中,因为受到各种因素的制约,比如第三方库或者后端接口返回的数据往往不确定,加之性能上影响其实并不是很大,所以为了保证数据正确性,对这块的约束一般并不是太严格。

结论:在自己能够预见的场景中尽量使用int short甚至byte来代替longfloat之于double同理。

包装类的使用场景

虽然Java中针对每种基本数据类型,都有包装类来对应,而且对应的包装类都提供了自动装箱和自动拆箱的能力,但是包装类也不能滥用。因为在给包装类赋值的时候,实际是通过valueOf方法去新建了一个对象,而基本数据类型的赋值却是直接在栈空间内完成的,效率就快了很多。
但是不是包装类就不要用了?也不是。包装类作为对象,提供了很多相关的操作方法,方便操作;另一方面,包装类可以很方便地区分赋值与未赋值的情况,而基本数据类型无法区分。这是在调用后端接口时经常会碰到的情况,所以不能一概而论。

结论:尽量使用基本数据类型来赋值以提高效率;但是在区分赋值和未赋值的场景时请使用包装类

变量修饰符的选择

修饰符分为访问控制修饰符和非访问控制修饰符。访问控制修饰符就是我们平时见到的private protected public 等对代码访问权限进行控制的符号,这里就不展开讲了;这里主要谈谈非访问控制修饰符,常用的就是static final 这两个(volatile也先略过不提)。

static 静态修饰符 使用了该修饰符,则表示该变量随着当前类的生命周期共存亡,并且该变量会被存到方法区(JVM中的一块固定区域)因而可被所有对象共享,即所有实例都可以通过类名来使用该变量

final 最终修饰符 使用了该修饰符,则表示此变量的生存期内,值是不可能改变的。常量如果使用final来修饰的话,读取效率较高。

结论:很明显,如果是常量,那么使用 static final 来修饰是可以提高效率的。


正确选择数据结构

在选择数据结构的时候,我们有时会选择用得最顺手的那个。殊不知,不同的数据结构,执行效率千差万别。正确选择更好更高效的数据结构是代码优化必须做到的。

ArrayList & LinkedList

这两个数据结构都是继承于AbstractList并实现了List接口,不同之处在于ArrayList底层数据结构使用的是数组,而 LinkedList底层数据结构使用的是链表。因此在什么场合使用就很明显了。

结论:随机查找与修改元素,使用ArrayList效率更高;对于新增和删除元素较多的场景,则最好使用LinkedList这是由数组和链表的性质决定的

HashMap & HashSet & HashTable

这三个数据结构都是基于Hash算法的数据结构,但是底层实现都不一样。HashMapHashTable 都是实现了Map 接口,但是前者继承AbstractMap且非线程安全,后者继承的是Dictionary是线程安全的;而HashSet实现的则是Set接口,而且效率相对于HashMap要低一些

结论:这几个实现Hash算法的数据结构,弄清楚了他们之间的区别和联系,就能明白使用场景了

SparseArray & HashMap

具体来说,SparseArray 是 Android 官方推荐的一种用来代替HashMap的数据结构,更加节省内存。但是在查找效率上,SparseArray由于查找核心算法是二分查找,比HashMap稍慢一点,但是相对来说效率损失并不是很大。

结论:在需要节省内存空间,或者对增删改查效率要求不是非常苛刻的场景,优先使用SparseArray

Serializable & Parcelabel

同样的,Parcelabel 也是 Android 官方推荐的一种序列化/反序列化代码的数据结构,比 Serializable 更加高效。因为在读写数据的时候,Parcelabel 是直接在内存中读写数据,而 Serializable 是通过 I/O 方式将数据读写在磁盘上,显然前者读写速度更快

结论:优先使用 Parcelabel 序列化/反序列化,但一些场景中还是需要使用 Serializable


善于使用位运算

在某些特定场景中,使用移位运算比直接乘除效率要高很多,这是由计算机底层特性决定的。比如 i / 2 就可以表示为 i >> 1

结论:培养习惯,看到这种场景要下意识想到使用位运算。但这样会导致代码可读性变差,所以请清楚注释


复用对象

因为生成一个新对象在 Java 虚拟机中是一个比较耗时耗性能的操作,而且在用完这个新对象之后,系统还要对这些生成的对象进行GC,这又是一笔性能开销。所以,频繁生成过多的对象对性能会造成很大影响。

结论:不要创建非必须的对象,能复用尽量复用。尤其是要避免在循环体内新建对象,避免内存抖动


减少不必要的全局变量

因为临时变量都保存在栈里,读取速度比堆中要快;另外,栈中的变量在方法结束时就销毁了,不需要进行额外的GC。

结论:在不需要的地方尽量不要使用全局变量


在类的内部直接访问变量

请在类的内部直接访问私有变量,而不是通过 get set 方法来访问,可以提高代码运行效率。get set 方法是提供给外部调用的

根据Android官方文档,在没有JIT(Just In Time)编译器时,直接访问变量的速度是调用Getter方法的3倍;在JIT编译时,直接访问变量的速度是调用Getter方法的7倍


循环体中的注意事项

循环体往往是影响效率的关键环节,一些影响效率的因素,原理其实很简单,所以直接说结论。

  1. 尽量避免在循环体中新建对象以减少内存抖动
  2. 不要把 try ... catch 语句写在循环体内部

善用Lint进行静态代码分析

Lint是个非常有用的工具,一般根据Lint的提示,可以改进很多代码中不规范的地方,提高效率。具体使用就不展开讲了,网上一搜一大把


暂时先写这么多,以后有补充再更新

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容