【问题标题】:SparseArray, check if key existsSparseArray,检查键是否存在
【发布时间】:2012-09-08 16:56:16
【问题描述】:

我正在使用 HashMap<Integer, Bitmap> 实现位图缓存,并在 Eclipse 中收到以下警告:

使用 new SparseArray(...) 代替以获得更好的性能。

我以前从未听说过该类,但检查它似乎没有containsKey() 方法,我调用该方法从缓存中检索位图以检查它是否存在于缓存中,并且如果没有,则添加它。

关于检查密钥是否已存在的最佳方法的任何想法?

我想我可以更改代码以使用此重载并检查 null 吗?

Bitmap bitmap = cache.get(key, null); 

【问题讨论】:

    标签: java android hashmap sparse-array


    【解决方案1】:

    多种方式:

    1. 如果你想使用与键关联的值,你可以使用get()

      val sparseArray = SparseArray<String>()
      val someKey = 123
      val someValue: String? = sparseArray[someKey]
      if(someValue!=null){
          //do something
      }
      

    请注意,与 IDE 的想法相反,它可以为 null,这就是我添加 ? 的原因。

    1. 如果只想检查是否存在,可以使用indexOfKey(key) &gt;= 0

    2. 如果你不喜欢上面的,想要一个更易读的选项,你可以使用 ktx-collection 依赖的containsKey

      implementation 'androidx.core:core-ktx:#'
      implementation 'androidx.collection:collection-ktx:#'
      

    用法:

        val sparseArray = SparseArray<String>()
        val someKey = 123
        if (sparseArray.containsKey(someKey)) {
            //do something
        }
    

    【讨论】:

      【解决方案2】:

      因此您的值在各种情况下可能为空,我建议使用indexOfKey(int key) 这是indexOfKey(int key) 参考。

      然后只需检查负返回值

      if(mySparseArray.indexOfKey(int) < 0) {
         //Item does not exist. Do something relevant 
      }
      

      【讨论】:

      • 这是否比仅使用 .get 更好/更差?
      • .get(int) 是 O(1) 因为它直接检查底层数组。 indexOf(int) 是 O(log(n)),因为它执行二进制搜索以找到正确的索引
      • @mylovemhz 错了! get(int) 中的 int 不是索引,而是键。因此,它不是 O(1)。 get(int)indexOfKey(int) 的复杂度相同 O(log(n)),一个返回该位置的值,否则返回 null,另一个只返回索引,否则返回负值。
      • 没错,get(int)indexOfKey(int) 都进行二分搜索。我的错。
      【解决方案3】:

      通过 SparseArray 的实现,它可能具有比 HashMap 更好的性能(时间复杂性)(除了对移动环境有意义的较低空间需求),因为 SparseArray 的 get() 成员似乎违反直觉使用二分查找 (O(log N)) 而 HashMap 使用数组索引 (O(1))。

      为两个类提供 get() 方法实现(原样):

      public V get(Object key) { // for HashMap
          if (key == null)
              return getForNullKey();
          int hash = hash(key.hashCode());
          for (Entry<K,V> e = table[indexFor(hash, table.length)];
                  e != null;
                  e = e.next) {
              Object k;
              if (e.hash == hash && ((k = e.key) == key || key.equals(k)))
                  return e.value;
          }
          return null;
      }
      
      public E get(int key, E valueIfKeyNotFound) {  //for SparseArray
          int i = binarySearch(mKeys, 0, mSize, key);
      
          if (i < 0 || mValues[i] == DELETED) {
              return valueIfKeyNotFound;
          } else {
              return (E) mValues[i];
          }
      }
      

      关于是否使用 indexOfKey(key)

      public int indexOfKey(int key) {  // for SparseArray
          if (mGarbage) {
              gc();
          }
      
          return binarySearch(mKeys, 0, mSize, key);
      }
      

      【讨论】:

      • 我不明白您对问题的回答与哪里有联系。
      【解决方案4】:

      你可以使用:

      Bitmap bitmap = cache.get(key, null); 
      

      但要明白这和get(key)是一样的:

      Bitmap bitmap = cache.get(key); 
      

      使用get(key, default) 的最佳方式是提供一个通用的默认情况,当找不到密钥时,它是一个有效的替代品

      但是没有充分的理由不使用if(get(key) != null) 来快速替代contains()

      【讨论】:

      • 谢谢山姆,关于过载的好地方,我同意你的建议,只用 if (get(key) != null) 替换。
      • 我检查 get() 是否为空。像 contains() (API 30) 这样的新方法之所以危险,是因为如果您的测试设备 API 足够高,它们将在没有警告的情况下编译和运行。后来,下载生产代码的旧 API 用户设备崩溃。
      【解决方案5】:

      引用自documentation

      SparseArrays 将整数映射到对象。与普通的对象数组不同,索引中可能存在间隙。它旨在比使用 HashMap 将整数映射到对象更有效。

      您可以使用get(int),如果找不到密钥,它也会返回 null。喜欢;

      位图 bitmap = cache.get(key);

      【讨论】:

      • 键可能有空值,在这种情况下,您的代码将无法确定键是否存在。即如果 key 不存在,它将返回 null,如果 key 具有 null 值,它也将返回 null。在这种情况下 indexOfKey 应该是用户(参见 Alex 的回答)
      • @user1991679 很老的答案,你的建议是我猜是通过更新的api。但是,对您的评论的回答是,int 原语不能为空。
      • 我不明白原语不能为空的事实与我的评论有何关系。顺便说一句,indexOfKey 是在 API 1 中引入的。
      • @uset1991679 好的,我明白你现在的意思了,但我认为问题并不是关于空值。或者那是我的看法。
      • @user1991679 sparsearray 不应该是地图。它是一个数组,很长。像普通数组一样,您应该得到一个空值或引用。如果您需要检查键是否存在,那么您可能需要映射而不是数组。我认为这就是亚历克斯的回答不相关的原因。
      猜你喜欢
      • 2023-03-30
      • 2015-12-04
      • 1970-01-01
      • 2020-02-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多