如何迭代SparseArray?

有没有一种方法来迭代Java SparseArray(Android版)? 我用sparsearray很容易通过索引获取值。 我找不到一个。

似乎我find了解决scheme。 我没有正确注意到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); } 

如果你不关心关键字,那么可以在迭代稀疏数组的时候使用valueAt(int)来直接访问这些值。

 for(int i = 0, nsize = sparseArray.size(); i < nsize; i++) { Object obj = sparseArray.valueAt(i); } 

你只需创build自己的ListIterator:

 public final class SparseArrayIterator<E> implements ListIterator<E> { private final SparseArray<E> array; private int cursor; private boolean cursorNowhere; /** * @param array * to iterate over. * @return A ListIterator on the elements of the SparseArray. The elements * are iterated in the same order as they occur in the SparseArray. * {@link #nextIndex()} and {@link #previousIndex()} return a * SparseArray key, not an index! To get the index, call * {@link android.util.SparseArray#indexOfKey(int)}. */ public static <E> ListIterator<E> iterate(SparseArray<E> array) { return iterateAt(array, -1); } /** * @param array * to iterate over. * @param key * to start the iteration at. {@link android.util.SparseArray#indexOfKey(int)} * < 0 results in the same call as {@link #iterate(android.util.SparseArray)}. * @return A ListIterator on the elements of the SparseArray. The elements * are iterated in the same order as they occur in the SparseArray. * {@link #nextIndex()} and {@link #previousIndex()} return a * SparseArray key, not an index! To get the index, call * {@link android.util.SparseArray#indexOfKey(int)}. */ public static <E> ListIterator<E> iterateAtKey(SparseArray<E> array, int key) { return iterateAt(array, array.indexOfKey(key)); } /** * @param array * to iterate over. * @param location * to start the iteration at. Value < 0 results in the same call * as {@link #iterate(android.util.SparseArray)}. Value > * {@link android.util.SparseArray#size()} set to that size. * @return A ListIterator on the elements of the SparseArray. The elements * are iterated in the same order as they occur in the SparseArray. * {@link #nextIndex()} and {@link #previousIndex()} return a * SparseArray key, not an index! To get the index, call * {@link android.util.SparseArray#indexOfKey(int)}. */ public static <E> ListIterator<E> iterateAt(SparseArray<E> array, int location) { return new SparseArrayIterator<E>(array, location); } private SparseArrayIterator(SparseArray<E> array, int location) { this.array = array; if (location < 0) { cursor = -1; cursorNowhere = true; } else if (location < array.size()) { cursor = location; cursorNowhere = false; } else { cursor = array.size() - 1; cursorNowhere = true; } } @Override public boolean hasNext() { return cursor < array.size() - 1; } @Override public boolean hasPrevious() { return cursorNowhere && cursor >= 0 || cursor > 0; } @Override public int nextIndex() { if (hasNext()) { return array.keyAt(cursor + 1); } else { throw new NoSuchElementException(); } } @Override public int previousIndex() { if (hasPrevious()) { if (cursorNowhere) { return array.keyAt(cursor); } else { return array.keyAt(cursor - 1); } } else { throw new NoSuchElementException(); } } @Override public E next() { if (hasNext()) { if (cursorNowhere) { cursorNowhere = false; } cursor++; return array.valueAt(cursor); } else { throw new NoSuchElementException(); } } @Override public E previous() { if (hasPrevious()) { if (cursorNowhere) { cursorNowhere = false; } else { cursor--; } return array.valueAt(cursor); } else { throw new NoSuchElementException(); } } @Override public void add(E object) { throw new UnsupportedOperationException(); } @Override public void remove() { if (!cursorNowhere) { array.remove(array.keyAt(cursor)); cursorNowhere = true; cursor--; } else { throw new IllegalStateException(); } } @Override public void set(E object) { if (!cursorNowhere) { array.setValueAt(cursor, object); } else { throw new IllegalStateException(); } } } 

使用上述循环从SparseArray移除所有元素将导致Exception

为了避免这种情况请按照以下代码使用普通循环从SparseArray删除所有元素

 private void getValues(){ for(int i=0; i<sparseArray.size(); i++){ int key = sparseArray.keyAt(i); Log.d("Element at "+key, " is "+sparseArray.get(key)); sparseArray.remove(key); i=-1; } } 

简单如馅饼。 只要确保实际执行循环之前获取数组大小。

 for(int i = 0, arraySize= mySparseArray.size(); i < arraySize; i++) { Object obj = mySparseArray.get(/* int key = */ mySparseArray.keyAt(i)); } 

希望这可以帮助。

这里是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); } } 

创build返回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)) { // ... } 

对于使用Kotlin的人来说,说实话,迭代SparseArray的最简单的方法是:使用Anko的Kotlin扩展!

只需拨打forEach { i, item -> }

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

你可以从0 - size()循环,并跳过返回null ,但这是关于它。

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

 TreeMap<Integer, MyType> 

被接受的答案有一些漏洞。 SparseArray的美妙之处在于它允许indeces中的空白。 所以,我们可以像SparseArray一样有两个地图…

 (0,true) (250,true) 

注意这里的大小是2.如果我们遍历大小,我们只会得到映射到索引0和索引1的值的值。所以不能访问具有250的键的映射。

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

最好的方法是遍历数据集的大小,然后使用get()检查这些数组。 这里是一个适配器的例子,我允许批量删除项目。

 for (int index = 0; index < mAdapter.getItemCount(); index++) { if (toDelete.get(index) == true) { long idOfItemToDelete = (allItems.get(index).getId()); mDbManager.markItemForDeletion(idOfItemToDelete); } } 

我想最理想的是SparseArray系列将有一个getKeys()方法,但是它不。