如何遍历 SparseArray | Java Debug 笔记

2,184 阅读2分钟

本文正在参加「Java主题月 - Java Debug笔记活动」,详情查看 活动链接

问题

有没有一种方法可以遍历 Java SparseArray(针对 Android),我用 sparsearray 很容易就通过索引来获取到对应值,单并没有找到遍历的方法。

回答

回答 1

看来我找到了解决方案,我没有正确注意到 keyAt(index) 方法的作用,所以我会这样做:

for(int i = 0; i < sparseArray.size(); i++) {
   int key = sparseArray.keyAt(i);
   // 通过键值获取对象
   Object obj = sparseArray.get(key);
}

回答 2

或许你只需要创建你自己的 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();
        }
    }
}

回答 3

老实讲,不管是谁使用 Kotlin,目前来看最简单的遍历 SparseArray 的方法是:使用 Kotlin 的扩展(Anko 或者 Android KTX

只需要调用 forEach {i, item ->} 即可。

出处

文章翻译自 Stack Overflow:How to iterate through SparseArray?