android开发分享荐 灵魂一问,Android中有代替HashMap的方法吗?

什么是HashMap?简单的说就是用来存放映射关系数据的一个集合工具,就是一个Key,对应一个Value,通过指定Key,可以查找对应Value。他在JDK1.7和JDK1.8或以后的实现方法不同,1.7是数组+链表,1.8则是数组+链表+红黑树结构,(当链表长度大于8,转为红黑树)。当然还有很多不同的地方。为什么要代替HashMap?就像我们生活中一样,一个东西被替代,无非就是新的更好而已,而且具有旧的所有功能。那我们为什么有理由不去使用他呢?在Android中可以代替HashMap的类是Spar


什么是HashMap?

简单的说就是用来存放映射关系数据的一个集合工具,就是一个Key,对应一个Value,通过指定Key,可以查找对应Value。他在JDK1.7和JDK1.8或以后的实现方法不同,1.7是数组+链表,1.8则是数组+链表+红黑树结构,(当链表长度大于8,转为红黑树)。当然还有很多不同的地方。

为什么要代替HashMap?

就像我们生活中一样,一个东西被替代,无非就是新的更好而已,而且具有旧的所有功能。那我们为什么有理由不去使用他呢?

在Android中可以代替HashMap的类是SparseArray,他比HashMap更节省内存,因为它避免了自动装箱操作,也就是int转为Integer类型,哦忘了说了,SparseArray的Key只能为int,也就是当我们只有在key是int的时候才可以使用SparseArray,其实还有SparseIntArray、SparseLongArray、SparseBooleanArray类。那我的key是其他的类型时候呢?当然还有其他办法,那就是ArrayMap。

还有就是SparseArray并不像HashMap采用一维数组+单链表结构,而是采用两个一维数组,一个是存储key(int类型),一个是存在value。

private int[] mKeys;  private Object[] mValues; 

怎么使用SparseArray?

使用他其实和HashMap类似,实例化、put…,SparseArray如果不指定容量,默认是10大小。

 public SparseArray() {      this(10);  } 

插入

SparseArray<Book> bookSparseArray = new SparseArray<>(); bookSparseArray.put(1,new Book("武林秘籍")); bookSparseArray.put(4,new Book("葵花宝典")); bookSparseArray.put(2,new Book("十八掌")); Log.i("TAG", "onCreate: "+bookSparseArray.get(2).getName()); 

输出:

 I/TAG: onCreate: 十八掌 

但是SparseArray还提供了一个append方法,也可以用来添加,

bookSparseArray.put(1,new Book("武林秘籍")); bookSparseArray.put(4,new Book("葵花宝典")); bookSparseArray.put(2,new Book("十八掌")); bookSparseArray.append(3,new Book("九阳真经")); Log.i("TAG", "onCreate: "+bookSparseArray.get(3).getName()); 

从源码第一句可以看出,如果数量不为0,并且新增的key小于等于mKeys[mSize – 1],就调用put方法,也就是如果新增的key大于现有的所有键时进行优化。

public void append(int key, E value) {     if (mSize != 0 && key <= mKeys[mSize - 1]) {         put(key, value);         return;     }     if (mGarbage && mSize >= mKeys.length) {         gc();     }     mKeys = GrowingArrayUtils.append(mKeys, mSize, key);     mValues = GrowingArrayUtils.append(mValues, mSize, value);     mSize++; } 

和HashMap不同的是,SparseArray提供了valueAt、keyAt用来查找指定索引位置的值、指定索引位置的key是多少。

 SparseArray<Book> bookSparseArray = new SparseArray<>();  bookSparseArray.put(1,new Book("武林秘籍"));  bookSparseArray.put(4,new Book("葵花宝典"));  bookSparseArray.put(2,new Book("十八掌"));  bookSparseArray.append(3,new Book("九阳真经"));  Log.i("TAG", "onCreate: "+bookSparseArray.valueAt(2).getName());  Log.i("TAG", "onCreate: "+bookSparseArray.keyAt(3)); 

输出:

I/TAG: onCreate: 九阳真经 I/TAG: onCreate: 4 

输出的结果是不是意想不到?其实在put的时候做了一些处理,SparseArray会根据Key自动排序(生序)。
荐                                                         灵魂一问,Android中有代替HashMap的方法吗?
荐                                                         灵魂一问,Android中有代替HashMap的方法吗?

删除

删除为我们提供了removeAt、remove、delete,分为是删除指定索引位置的数据,删除指定key、删除指定key。remove和delete是等价的,都一样。

 public void remove(int key) {      delete(key);  } 

还有一个是移除指定区间的removeAtRange。

 SparseArray<Book> bookSparseArray = new SparseArray<>();  bookSparseArray.put(1,new Book("武林秘籍"));  bookSparseArray.put(4,new Book("葵花宝典"));  bookSparseArray.put(2,new Book("十八掌"));  bookSparseArray.append(3,new Book("九阳真经"));  Log.i("TAG", "onCreate: "+bookSparseArray.valueAt(2).getName());  bookSparseArray.remove(2);  Log.i("TAG", "onCreate: "+bookSparseArray.valueAt(2).getName());  bookSparseArray.removeAtRange(0,bookSparseArray.size());  Log.i("TAG", "onCreate: "+bookSparseArray.size()); 

输出

I/TAG: onCreate: 九阳真经 I/TAG: onCreate: 葵花宝典 I/TAG: onCreate: 0 

获取

我们除了根据指定key获取对应值,get方法还有一个重载方法,这个方法提供了当key不存在的时候返回的默认值。

 public E get(int key, E valueIfKeyNotFound) {      int i = ContainerHelpers.binarySearch(mKeys, mSize, key);      if (i < 0 || mValues[i] == DELETED) {          return valueIfKeyNotFound;      } else {          return (E) mValues[i];      }  } 
 SparseArray<Book> bookSparseArray = new SparseArray<>();  bookSparseArray.put(1,new Book("武林秘籍"));  bookSparseArray.put(4,new Book("葵花宝典"));  bookSparseArray.put(2,new Book("十八掌"));  bookSparseArray.append(3,new Book("九阳真经"));  Book valueBook = bookSparseArray.get(5, new Book("空手套白狼"));  Log.i("TAG", "onCreate: "+valueBook.getName()); 

设置指定索引位置的值

SparseArray<Book> bookSparseArray = new SparseArray<>(); bookSparseArray.put(1,new Book("武林秘籍")); bookSparseArray.put(4,new Book("葵花宝典")); bookSparseArray.put(2,new Book("十八掌")); bookSparseArray.append(3,new Book("九阳真经")); Log.i("TAG", "onCreate: "+bookSparseArray.valueAt(2).getName()); bookSparseArray.setValueAt(2,new Book("听风逝夜")); Log.i("TAG", "onCreate: "+bookSparseArray.valueAt(2).getName()); 

输出

 I/TAG: onCreate: 九阳真经  I/TAG: onCreate: 听风逝夜 

二分法

在SparseArray中用到了二分法,用来查找key的索引位置。二分法查找针对的是一个有序的数据集合,每次通过与区间的中间元素对比,将待查找的区间缩小为之前的一半,直到找到要查找的元素,或者区间被缩小为0。

下面是ContainerHelpers类下的binarySearch方法实现,当然这个类我们访问不到。但是我们可以使用Collections.binarySearch或者Arrays.binarySearch。

static int binarySearch(int[] array, int size, int value) {     int lo = 0;     int hi = size - 1;     while (lo <= hi) {         final int mid = (lo + hi) >>> 1;         final int midVal = array[mid];         if (midVal < value) {             lo = mid + 1;         } else if (midVal > value) {             hi = mid - 1;         } else {             return mid;          }     }     return ~lo;   } 
 int[] data ={1,3,4,6,7,9};  Log.i("TAG", "2的索引位置: "+binarySearch(data,data.length,2));  Log.i("TAG", "1的索引位置: "+binarySearch(data,data.length,1));  Log.i("TAG", "9的索引位置: "+binarySearch(data,data.length,9)); 

输出如下,如果找不到,是返回负数的,这个负数也是具有意义的,称之为插入点,插入点值就是第一个比key大的元素在数组中的位置索引,而且这个位置索引从1开始。

 I/TAG: 2的索引位置: -2  I/TAG: 1的索引位置: 0  I/TAG: 9的索引位置: 5 

对于上面数据,如果我们查找10,那么会返回-7。或者大于9的数都会返回-7。

本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。

ctvol管理联系方式QQ:251552304

本文章地址:https://www.ctvol.com/addevelopment/896611.html

(0)
上一篇 2021年10月22日
下一篇 2021年10月22日

精彩推荐