@linux1s1s
2019-02-15T10:36:04.000000Z
字数 2663
阅读 3869
AndroidExtend 2015-10
我们经常看到下面三种Java的遍历方式。
List<String> testList = new ArrayList<String>();//Init testList here//Manual testList here//For Indexfinal int size = testList.size();for (int i = 0; i < size; i++) {final String s = testList.get(i);//TODO}//For Simplefor (String s : testList) {//TODO}//For Interatorfor (Iterator iterator = testList.iterator(); iterator.hasNext();) {String s = (String) iterator.next();//TODO}
这些遍历方式迥异,所以有必要探究一下他们在Android上的表现如何

从上面可以看到for index的方式有更好的效率,但是因为不同平台编译器优化各有差异,我们最好还是针对实际的方法做一下简单的测量比较好,拿到数据之后,再选择效率最高的那个方式。(一般建议选择for index的方式遍历)
我们经常会使用到HashMap这个容器,它非常好用,但是却很占用内存。为了解决HashMap更占内存的弊端,Android提供了内存效率更高的ArrayMap。它内部使用两个数组进行工作,其中一个数组记录key hash过后的顺序列表,另外一个数组按key的顺序记录Key-Value值。
因为ArrayMap在存储上是连续的。不像HashMap是不连续的,所以ArrayMap的插入与删除的效率是不够高的,但是如果数组的列表只是在一百这个数量级上,则完全不用担心这些插入与删除的效率问题。HashMap与ArrayMap之间的内存占用效率对比图如下:

不服可以来看一下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() {mHashes = ContainerHelpers.EMPTY_INTS;mArray = ContainerHelpers.EMPTY_OBJECTS;mSize = 0;}
上面说了辣么多废话,之类小结一下Map的使用。
//使用HashMap处理数据(数量级在千级别以上)HashMap<String, String> configMap = new HashMap<String, String>();//方式一for (Iterator iterator = configMap.entrySet().iterator(); iterator.hasNext();) {Map.Entry<String, String> entry = (Entry<String, String>) iterator.next();String key = entry.getKey();String value = entry.getValue();}//或者另外一种等效方式Iterator<Entry<String, String>> iterator = configMap.entrySet().iterator();while (iterator.hasNext()) {Map.Entry<String, String> entry = (Map.Entry<String, String>) iterator.next();String key = entry.getKey();String value = entry.getValue();}//方式二Iterator<String> iterator2 = configMap.keySet().iterator();while (iterator2.hasNext()) {String key = iterator2.next();String value = configMap.get(key);}//使用ArrayMap处理数据(数量级在百级别)ArrayMap<String, String> configMapRefine = new ArrayMap<String, String>();for (int i = 0; i < 500; i++) {String key = configMapRefine.keyAt(i);String value = configMapRefine.valueAt(i);}
另外还有一种Android专门优化的Map-SparseArray,什么情况下适用SparseArray呢?

看清楚,只有在Map<Integer, String>这种情况下才适用SparseArray替换
SparseArray<String> sparseArray = new SparseArray<String>();for (int i = 0; i < sparseArray.size(); i++) {int key = sparseArray.keyAt(i);String value = sparseArray.valueAt(i);}
具体在性能上能优化多少可以参考 SparseArray替代HashMap来提高性能 。
关于Enum,Android官方开发文档有这么一句话:

Enums often require more than twice as much memory as static constants. You should strictly avoid using enums on Android.
关于enum的效率,请看下面的讨论。假设我们有这样一份代码,编译之后的dex大小是2556 bytes,在此基础之上,添加一些如下代码,这些代码使用普通static常量相关作为判断值:
增加上面那段代码之后,编译成dex的大小是2680 bytes,相比起之前的2556 bytes只增加124 bytes。假如换做使用enum,情况如下:
使用enum之后的dex大小是4188 bytes,相比起2556增加了1632 bytes,增长量是使用static int的13倍。不仅仅如此,使用enum,运行时还会产生额外的内存占用,如下图所示:

