安卓下HashMap与SparseArray在适配器中的误用

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/Mingyueyixi/article/details/52653841

近段时间,在安卓中使用了大量的SparseArray,原因是使用HashMap时,提示说用SparseArray代替。然后据说这样可以获取更高的性能。于是,就开始各种迷信地到处使用了。

结果,出了问题鸟。


key存图片的id,value存TextView的字符串,因为它们是成对匹配的。

然后在适配器方法中这么使用了:

@Override
public View getView(int position, View convertView, ViewGroup parent) {

tv_item.setText(lists.valueAt(position));

img_item.setImageResource(lists.keyAt(position));
}

OO,OO。悲剧出来了。文字和图片是成对出现了,但item的顺序却错了,也就说文字和图片放错了item。


于是,使用循环的方法,将SparseArray与HashMap中的数据按照索引逐一打印出来。结果发现,它们之中的东西不是按照put(key,value)方法的先后存在的。居然给自动排序了。或者说被打乱了顺序。所以,当需要按照插入的顺序来进行操作时,是不能够通过HashMap或SparseArray的形式存放相关Id到它的key中的。否则顺序会乱掉。

在这个适配器方法中,适配器通过getView按顺序分配position,生成view用来显示。所以,这么搞不适用的。

解决的办法:

按老办法,封装一个类,存入图片id和文字。而这样做,也不必再使用HashMap这种形式了。

一个是使用具有插入顺序的LinkedHashMap。

而安卓中似乎就没有了针对的优化了,大概是没的优化了。

LinkedHashMap的使用:


LinkedHashMap<Integer,String> items = new LinkedHashMap<Integer,String>();


获取指定索引位置的值:

String str1 = (String) items.values().toArray()[1];


获取指定索引位置的键:

int int1 = (Integer) items.keySet().toArray()[2];


LinkedHashMap的遍历和Map的遍历一样:

for遍历


for (Iterator it =  items.keySet().iterator();it.hasNext();){
			Object key = it.next(); 
			key = items.get(key);

		}


while遍历


        Iterator<Map.Entry> iterator= linkedHashMap.entrySet().iterator();

        while(iterator.hasNext())
        {
            Map.Entry entry = iterator.next();
            System.out.println(entry.getKey()+":"+entry.getValue());
        }






测试代码:

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		SparseArray<String> sparseArray = new SparseArray<>();
		sparseArray.put(6, "第六");
		sparseArray.put(1, "第一");
		sparseArray.put(4, "第四");
		sparseArray.put(2, "第二");
		sparseArray.put(3, "第三");
		sparseArray.put(5, "第五");
		sparseArray.put(7, "第七");
		sparseArray.put(8, "第八");
		
		HashMap<Integer, String> hashMap = new HashMap<>();
		hashMap.put(6, "第六");
		hashMap.put(1, "第一");
		hashMap.put(4, "第四");
		hashMap.put(2, "第二");
		hashMap.put(3, "第三");
		hashMap.put(5, "第五");
		hashMap.put(7, "第七");
		hashMap.put(8, "第八");
		
		String TAG = "测试";
		//遍历输出
		for (int i = 0; i < sparseArray.size(); i++) {
			Log.e(TAG, "=========SparseArray遍历测试======");
			Log.e(TAG, sparseArray.keyAt(i)+" ====key--value==== "+sparseArray.valueAt(i));
		}
		
		//遍历输出
		for (int i = 0; i < hashMap.size(); i++) {
			Log.e(TAG, "=========HashMap遍历测试======");
			Log.e(TAG, sparseArray.keyAt(i)+" ====key--value==== "+sparseArray.valueAt(i));
		}
		
	}



结果如下:


09-24 22:28:41.197: E/测试(1913): =========SparseArray遍历测试======
09-24 22:28:41.197: E/测试(1913): 1 ====key--value==== 第一
09-24 22:28:41.201: E/测试(1913): 2 ====key--value==== 第二
09-24 22:28:41.213: E/测试(1913): 3 ====key--value==== 第三
09-24 22:28:41.213: E/测试(1913): 4 ====key--value==== 第四
09-24 22:28:41.213: E/测试(1913): 5 ====key--value==== 第五
09-24 22:28:41.213: E/测试(1913): 6 ====key--value==== 第六
09-24 22:28:41.213: E/测试(1913): 7 ====key--value==== 第七
09-24 22:28:41.213: E/测试(1913): 8 ====key--value==== 第八
09-24 22:28:41.213: E/测试(1913): =========HashMap遍历测试======
09-24 22:28:41.213: E/测试(1913): 1 ====key--value==== 第一
09-24 22:28:41.213: E/测试(1913): 2 ====key--value==== 第二
09-24 22:28:41.213: E/测试(1913): 3 ====key--value==== 第三
09-24 22:28:41.213: E/测试(1913): 4 ====key--value==== 第四
09-24 22:28:41.213: E/测试(1913): 5 ====key--value==== 第五
09-24 22:28:41.213: E/测试(1913): 6 ====key--value==== 第六
09-24 22:28:41.213: E/测试(1913): 7 ====key--value==== 第七
09-24 22:28:41.213: E/测试(1913): 8 ====key--value==== 第八



SparseArray的官方说明如下:


android.util.SparseArray<String>

SparseArrays map integers to Objects. Unlike a normal array of Objects, there can be gaps in the indices. It is intended to be more memory efficient than using a HashMap to map Integers to Objects, both because it avoids auto-boxing keys and its data structure doesn't rely on an extra entry object for each mapping.

Note that this container keeps its mappings in an array data structure, using a binary search to find keys. The implementation is not intended to be appropriate for data structures that may contain large numbers of items. It is generally slower than a traditional HashMap, since lookups require a binary search and adds and removes require inserting and deleting entries in the array. For containers holding up to hundreds of items, the performance difference is not significant, less than 50%.

To help with performance, the container includes an optimization when removing keys: instead of compacting its array immediately, it leaves the removed entry marked as deleted. The entry can then be re-used for the same key, or compacted later in a single garbage collection step of all removed entries. This garbage collection will need to be performed at any time the array needs to be grown or the the map size or entry values are retrieved.

It is possible to iterate over the items in this container using keyAt(int) andvalueAt(int). Iterating over the keys usingkeyAt(int) with ascending values of the index will return the keys in ascending order, or the values corresponding to the keys in ascending order in the case ofvalueAt(int).







展开阅读全文

没有更多推荐了,返回首页