在开发中,我们经常会不在意一些小的性能损失,但是当这些损失积累起来就会引起大问题,我们在开发中还是需要谨小慎微来挖掘任何性能优化方法。

Java提供了基本类型如boolean(8bit)int(32bit)float(32bit)long(64bit)等。同时也相应提供了自动包装类型java.lang.Booleanjava.lang.Integerjava.langFloat等自动包装类型,通常用于集合类的使用(基本类型无法在集合类中使用)。这是自动包装类型产生的原因。

自动包装类型封装了基本类型常用的方法,我们不用担心功能上的问题。并且基本类型可以直接赋值给自动包装类而不需要转换。


//Primitive version
int total = 0;
for(int i=0;i<100;i++)
	total +=i ;

//Generic version
Integer total = 0;
for(int i=0;i<100;i++)
	total += i;
	//create new Integer(),
	//push in new value
	//add to total

上面的代码看起来基本类型和自动包装类型的使用并没有差别。但是我们要注意Java Runtime在后面到底做了什么。就像注释中标明的。自动包装类在每次循环都会new一个Integer对象,将i赋值到对象中,然后添加到total。在这自动包装类的循环中分配了83个对象(循环100次怎么不是分配了100个对象?我也觉得疑惑,我想这是Java底层为我们做的优化吧)。但是基本类型的循环没有分配对象。

Integer的自动包装类型占用内存16byte大小为int的4倍,这就会产生性能问题。

但是在JAVA提供的集合中我们却不得不使用自动包装类,特别是HashMap,我们只能使用自动包装类。

为解决这个问题Android为我们提供了自己的集合类型来解决这个问题:

  1. SparseBooleanArray<int,boolean>
  2. SparseArray<int,obj>
  3. SparseLongMap<int,long>
  4. LongSparseMap<long,obj>
  5. SparseIntArray<int,int>

这些集合类的实现与ArrayMaps一样,具体实现可以进入查看。

怎么查找我们的代码中哪里使用了自动包装呢?我们可以使用AndroidStudio提供的调试工具AllocationTracker和TraceView来查找。


IMAKIBA

Welcom to my blog!