是否有一种方法来迭代Java SparseArray (Android) ?我使用sparsearray很容易地按索引获取值。我找不到一个。


当前回答

看来我找到解决办法了。我没有正确地注意到keyAt(index)函数。

所以我会这样说:

for(int i = 0; i < sparseArray.size(); i++) {
   int key = sparseArray.keyAt(i);
   // get the object by the key.
   Object obj = sparseArray.get(key);
}

其他回答

这里是SparseArray<T>的简单Iterator<T>和Iterable<T>实现:

public class SparseArrayIterator<T> implements Iterator<T> {
    private final SparseArray<T> array;
    private int index;

    public SparseArrayIterator(SparseArray<T> array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return array.size() > index;
    }

    @Override
    public T next() {
        return array.valueAt(index++);
    }

    @Override
    public void remove() {
        array.removeAt(index);
    }

}

public class SparseArrayIterable<T> implements Iterable<T> {
    private final SparseArray<T> sparseArray;

    public SparseArrayIterable(SparseArray<T> sparseArray) {
        this.sparseArray = sparseArray;
    }

    @Override
    public Iterator<T> iterator() {
        return new SparseArrayIterator<>(sparseArray);
    }
}

如果你不仅要迭代一个值,还要迭代一个键:

public class SparseKeyValue<T> {
    private final int key;
    private final T value;

    public SparseKeyValue(int key, T value) {
        this.key = key;
        this.value = value;
    }

    public int getKey() {
        return key;
    }

    public T getValue() {
        return value;
    }
}

public class SparseArrayKeyValueIterator<T> implements Iterator<SparseKeyValue<T>> {
    private final SparseArray<T> array;
    private int index;

    public SparseArrayKeyValueIterator(SparseArray<T> array) {
        this.array = array;
    }

    @Override
    public boolean hasNext() {
        return array.size() > index;
    }

    @Override
    public SparseKeyValue<T> next() {
        SparseKeyValue<T> keyValue = new SparseKeyValue<>(array.keyAt(index), array.valueAt(index));
        index++;
        return keyValue;
    }

    @Override
    public void remove() {
        array.removeAt(index);
    }

}

public class SparseArrayKeyValueIterable<T> implements Iterable<SparseKeyValue<T>> {
    private final SparseArray<T> sparseArray;

    public SparseArrayKeyValueIterable(SparseArray<T> sparseArray) {
        this.sparseArray = sparseArray;
    }

    @Override
    public Iterator<SparseKeyValue<T>> iterator() {
        return new SparseArrayKeyValueIterator<T>(sparseArray);
    }
}

创建返回Iterable<T>和Iterable<SparseKeyValue<T>>的实用程序方法很有用:

public abstract class SparseArrayUtils {
    public static <T> Iterable<SparseKeyValue<T>> keyValueIterable(SparseArray<T> sparseArray) {
        return new SparseArrayKeyValueIterable<>(sparseArray);
    }

    public static <T> Iterable<T> iterable(SparseArray<T> sparseArray) {
        return new SparseArrayIterable<>(sparseArray);
    }
}

现在你可以迭代SparseArray<T>:

SparseArray<String> a = ...;

for (String s: SparseArrayUtils.iterable(a)) {
   // ...
}

for (SparseKeyValue<String> s: SparseArrayUtils.keyValueIterable(a)) {
  // ...
}

答案是否定的,因为SparseArray没有提供。正如pst所说,这个东西不提供任何接口。

您可以从0 - size()开始循环,并跳过返回null的值,但仅此而已。

正如我在我的评论中所述,如果你需要迭代使用Map而不是SparseArray。例如,使用按键顺序迭代的TreeMap。

TreeMap<Integer, MyType>

看来我找到解决办法了。我没有正确地注意到keyAt(index)函数。

所以我会这样说:

for(int i = 0; i < sparseArray.size(); i++) {
   int key = sparseArray.keyAt(i);
   // get the object by the key.
   Object obj = sparseArray.get(key);
}

对于使用Kotlin的人来说,老实说,到目前为止迭代SparseArray最简单的方法是:使用Anko或Android KTX的Kotlin扩展!(感谢Yazazzello指出Android KTX)

简单地调用forEach {i, item ->}

如果你使用Kotlin,你可以像这样使用扩展函数,例如:

fun <T> LongSparseArray<T>.valuesIterator(): Iterator<T> {
    val nSize = this.size()
    return object : Iterator<T> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next(): T = valueAt(i++)
    }
}

fun <T> LongSparseArray<T>.keysIterator(): Iterator<Long> {
    val nSize = this.size()
    return object : Iterator<Long> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next(): Long = keyAt(i++)
    }
}

fun <T> LongSparseArray<T>.entriesIterator(): Iterator<Pair<Long, T>> {
    val nSize = this.size()
    return object : Iterator<Pair<Long, T>> {
        var i = 0
        override fun hasNext(): Boolean = i < nSize
        override fun next() = Pair(keyAt(i), valueAt(i++))
    }
}

如果您愿意,还可以将其转换为列表。例子:

sparseArray.keysIterator().asSequence().toList()

我认为在LongSparseArray本身(而不是在迭代器上)上使用remove删除项可能是安全的,因为它是升序的。


编辑:似乎有一种更简单的方法,使用collection-ktx(示例)。实际上,它的实现方式与我写的非常相似。

Gradle要求:

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

下面是LongSparseArray的用法:

    val sparse= LongSparseArray<String>()
    for (key in sparse.keyIterator()) {
    }
    for (value in sparse.valueIterator()) {
    }
    sparse.forEach { key, value -> 
    }

对于那些使用Java的人,您可以使用LongSparseArrayKt。keyIterator, LongSparseArrayKt。valueIterator和LongSparseArrayKt。例如,对每个人。其他情况也一样。