This article is participating in the Java Theme Month – Java Debug Notes Event, see the event link for details

The problem

Is there a way to traverse Java SparseArray (for Android), I used SparseArray to easily get the corresponding value through the index, but did not find a way to traverse.

answer

Answer 1

It looks like I’ve found a solution. I didn’t notice the keyAt(index) method correctly, so I’ll do this:

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

Answer 2

Maybe you just need to create your own 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(a) {
        return cursor < array.size() - 1;
    }

    @Override
    public boolean hasPrevious(a) {
        return cursorNowhere && cursor >= 0 || cursor > 0;
    }

    @Override
    public int nextIndex(a) {
        if (hasNext()) {
            return array.keyAt(cursor + 1);
        } else {
            throw newNoSuchElementException(); }}@Override
    public int previousIndex(a) {
        if (hasPrevious()) {
            if (cursorNowhere) {
                return array.keyAt(cursor);
            } else {
                return array.keyAt(cursor - 1); }}else {
            throw newNoSuchElementException(); }}@Override
    public E next(a) {
        if (hasNext()) {
            if (cursorNowhere) {
                cursorNowhere = false;
            }
            cursor++;
            return array.valueAt(cursor);
        } else {
            throw newNoSuchElementException(); }}@Override
    public E previous(a) {
        if (hasPrevious()) {
            if (cursorNowhere) {
                cursorNowhere = false;
            } else {
                cursor--;
            }
            return array.valueAt(cursor);
        } else {
            throw newNoSuchElementException(); }}@Override
    public void add(E object) {
        throw new UnsupportedOperationException();
    }

    @Override
    public void remove(a) {
        if(! cursorNowhere) { array.remove(array.keyAt(cursor)); cursorNowhere =true;
            cursor--;
        } else {
            throw newIllegalStateException(); }}@Override
    public void set(E object) {
        if(! cursorNowhere) { array.setValueAt(cursor, object); }else {
            throw newIllegalStateException(); }}}Copy the code

Answer 3

Honestly, no matter who uses Kotlin, by far the easiest way to traverse SparseArray is to use the Kotlin extension (Anko or Android KTX).

Just call forEach {I, item ->}.

provenance

Stack Overflow: How to iterate through SparseArray?