Android SparseArray值比较

5

我写了一些非常简单的代码,发现了一个非常意外的行为。所有的ListMap实现都使用节点的equals方法进行比较。因此,如果你有一个字符串列表,并且尝试获取列表中一个字符串的索引,你不需要使用相同的对象。例如:

List<String> list = new ArrayList<>();
list.add("test");
int index = list.indexOf("test");
System.out.println(index);//returns 0

我注意到Android的所有SparseArray类都使用==而不是equals来比较节点。例如方法(LongSparseArray.java):

public int indexOfValue(E value) {
    if (mGarbage) {
    gc();
    }

for (int i = 0; i < mSize; i++) {
    if (mValues[i] == value) {
        return i;
        }
    }
        return -1;
}

如果您有类似以下这样的简单代码:

LongSparseArray<String> localContacts = new LongSparseArray<>();
localContacts.put(2, "test");
int index = localContacts.indexOfValue("test");
System.out.println(index);

这里的索引将返回-1(如果您不知道如何比较值,则这是非常意外的)。
所以我在想……为什么Android不使用“equals”呢?从Java的角度来看,这更方便和首选。现在我必须循环遍历所有SparseArray的值并自己进行比较,这会导致更多(不必要的)代码(或使用Map会在Android中降低性能)。

看起来你可以使用 indexOfValueByValue 来进行等值比较(编辑:算了,我发现这个方法由于某些原因被隐藏了)。 - PPartisan
1个回答

2

查看LongSparseArray的源代码,似乎这个方法确实存在,但是它被隐藏了(出于某种原因):

/**
* Returns an index for which {@link #valueAt} would return the
* specified key, or a negative number if no keys map to the
* specified value.
* <p>Beware that this is a linear search, unlike lookups by key,
* and that multiple keys can map to the same value and this will
* find only one of them.
* <p>Note also that this method uses {@code equals} unlike {@code indexOfValue}.
* @hide
*/
public int indexOfValueByValue(E value) {
    if (mGarbage) {
        gc();
    }

    for (int i = 0; i < mSize; i++) {
        if (value == null) {
            if (mValues[i] == null) {
                return i;
            }
        } else {
            if (value.equals(mValues[i])) {
                return i;
            }
        }
    }
    return -1;
}

你可以看到,这段代码所做的就是你在问题中说的 - 循环遍历所有值,直到找到正确的值,并返回其索引。
我不知道为什么这被排除在公共API之外,但在我看来,这是使用Sparse***的又一个缺点。它们通常过于基本,无法满足我的需求。

感谢澄清。我只使用SparseArrays来提高性能。 - Displee

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接